Every endpoint is listed in the sidebar, starting with . The conventions below apply to all of them.
- New to Courier? Send your first notification with the .
- Building with Claude Code, Codex, or Cursor? Connect Courier over MCP or the CLI. Start with .
- Prefer a GUI? Explore every endpoint in the .
Client libraries
Server SDKs wrap this API with typed methods, retries, and idempotency helpers. Prefer them over raw HTTP. Each page carries the install command and the current version.Node.js
Python
Ruby
Go
Java
PHP
C# / .NET
Authentication
Pass your API key as a bearer token in theAuthorization header:
401 Unauthorized. Keys are scoped to one , Test or Production, so a Test key never sends real notifications. Create and rotate keys in .
Requests and responses
- All requests and responses use JSON. Send
Content-Type: application/jsonon requests with a body. - Timestamps are Unix epoch milliseconds (
int64), not ISO 8601 strings. - Send responses return a
requestId. Use it to or trace delivery in Message Logs.
Payload limits
Request bodies cap at 6 MB on all endpoints. Larger requests return413 Payload Too Large.
Base64 content, such as inline attachments, inflates size by roughly 33%. A 6 MB payload holds about 4.5 MB of raw attachment data. For anything larger, host the file and pass a URL.
Idempotency
Send an idempotency key to retry safely without sending duplicates. Use a unique value, such as a UUID, per logical request, and reuse it when you retry. Server SDKs take it as a parameter and set theIdempotency-Key header for you.
POST only. Sending the header on any other method is accepted and does nothing, because the other methods are already idempotent by definition.
How long a response is replayed
Courier replays a response for 25 hours by default. Sendx-idempotency-expiration to hold a key longer, as an ISO 8601 datetime or a Unix epoch in milliseconds, up to one year. Anything else returns 400 Expiration is not a valid date.
- It is per endpoint, not global. The same key sent to
/sendand to/profiles/{user_id}creates two independent records. - Not every
POSTsupports it. Supported endpoints declareIdempotency-Keyamong their parameters. They include , , , and . - Keys are retained 25 hours by default. Hold one for up to a year with
x-idempotency-expiration, as described in How long a response is replayed.
Pagination
List endpoints use cursor-based pagination. Every response includes apaging object with a more boolean and a cursor:
paging.more is true, pass paging.cursor back as the cursor query parameter to fetch the next page:
results, while and return items. Check the endpoint’s own schema before you parse it.
Errors
Courier uses standard HTTP status codes.2xx is success, 4xx is a problem with your request, and 5xx is a Courier-side error.
Error responses include a JSON body with a human-readable
message and a machine-readable type:
Message statuses
A202 from means Courier accepted the request, not that the message was delivered. Track the outcome with , which returns one of these statuses:
ENQUEUED, ROUTED, SENT, DELIVERED, OPENED, CLICKED, DELAYED, DIGESTED, THROTTLED, FILTERED, CANCELED, SIMULATED, and three failure states:
UNROUTABLE: no channel could be resolved (missing provider, or no channel data on the profile)UNDELIVERABLE: the provider rejected the recipient (invalid address or blocked domain)UNMAPPED: the referenced template couldn’t be found
reason, such as BOUNCED, NO_PROVIDERS, OPT_IN_REQUIRED, or UNSUBSCRIBED.
Rate limits
is not rate-limited by request count, so you can send at volume. Instead, the you configure per user, topic, or tenant govern message volume. Three management endpoints are limited per workspace:
Endpoints not listed here aren’t request-count limited today. Limited responses carry
X-RateLimit-Limit and X-RateLimit-Remaining so you can pace requests. Exceeding a limit returns 429 Too Many Requests.
FAQ
What can you do with the Courier API?
What can you do with the Courier API?
Anything you can do in the Courier dashboard. Send notifications across email, SMS, push, chat, and in-app, and manage user profiles, preferences, lists, templates, brands, and tenants.
What is the Courier API base URL?
What is the Courier API base URL?
All requests go to
https://api.courier.com over HTTPS.How do I authenticate with the Courier API?
How do I authenticate with the Courier API?
Pass your API key as a bearer token in the
Authorization header: Authorization: Bearer YOUR_COURIER_API_KEY. Keys are scoped per environment (Test or Production) and used only in server-side code.Which languages have official Courier SDKs?
Which languages have official Courier SDKs?
Courier maintains official server SDKs for Node.js, Python, Ruby, Go, Java, PHP, and C# / .NET, plus client SDKs for React, React Native, iOS, Android, and Flutter. Any language can call the REST API directly.
What are the Courier API rate limits?
What are the Courier API rate limits?
isn’t limited by request count. Three management endpoints are limited per workspace (see the table above). Exceeding a limit returns
429 Too Many Requests.How do I avoid sending duplicate notifications on retry?
How do I avoid sending duplicate notifications on retry?
Set an
Idempotency-Key header with a unique value. Courier replays the original response for 25 hours, so a retried request runs only once.