Skip to main content
A send begins when your application calls the Courier API to send a message. Courier renders your content, determines which channels to use, and sends through your configured providers. Each message is tracked from request to delivery so you can monitor outcomes in real time. Courier provides a single source of truth for message observability across all channels.
Your App   →   Courier API   →   Providers   →   User
You decide what to send and who should receive it. Courier manages how it gets there. It handles routing, preferences, retries, and logging automatically. A single API call is all it takes to send a notification. One request handles rendering, routing, preferences, and delivery across every channel. See Send a Message for code examples in every supported language.

Core Concepts

Every send request is built around a few core ideas: Recipients
You can include contact details (email, phone, push token) directly in your request or reference a user_id linked to a stored user profile.
Templates
Define content inline or reference a saved template that your team manages visually. Templates keep messaging consistent across channels and editable without code changes.
Data
Pass dynamic variables like {{name}} or {{order_id}} to personalize content at send time.
Routing
Deliver messages using priority routing through a single channel or by broadcasting across multiple channels at once. Courier automatically selects the optimal route for each message.
User Preferences
Courier automatically enforces each user’s notification preferences at send time, respecting channel choices, frequency settings, and opt-outs without extra logic in your code.

Beyond Single Sends

The Send API handles the majority of notification use cases on its own. When your product needs more, Courier provides a natural path forward without requiring you to rearchitect. Templates let you move content out of your code so PMs and designers can update messaging independently. Your send call stays the same; you just reference a template ID instead of inline content. Automations add timing, sequencing, and conditional logic on top of sending. Use them for digest summaries, onboarding sequences, reminder chains, or any notification that depends on user behavior or elapsed time. Automations use the same templates, users, and preferences as direct sends. You start simple and layer on complexity only when you need it. See Choose a Sending Strategy for a detailed comparison of when to use each approach.

FAQ

Yes. Pass an array of recipients in the to field to send a single message to multiple users. You can also send to a List or Audience to target dynamic groups. For larger volumes, use the Bulk API to create a job, add users, and run the job asynchronously.
Courier automatically fails over based on your routing configuration. If the primary provider for a channel is unavailable, Courier tries the next configured provider. If the entire channel fails (e.g. the user has no email address), Courier moves to the next channel in priority order. See Automated Failover for details.
Courier retries failed sends automatically using exponential backoff. Transient errors from providers (rate limits, temporary outages) are retried before the send is marked as failed. You can monitor retry attempts and final delivery status in Message Logs.
Yes. Include an idempotency_key in your send request header. If Courier receives a second request with the same key, it returns the original response without sending again. This is useful for safely retrying requests after network failures.
Yes. Use the delay object in your send request to hold a message for a specified duration or until a specific time. See Delays & Delivery Windows for configuration options.