Skip to main content
One block per task. first, and export COURIER_API_KEY.

Send a notification

Only a published template sends. To send without one, pass --message.content with a JSON object holding title and body, instead of --message.template.

Manage profiles

create merges into an existing profile. replace overwrites it, so include every field you want to keep.

Check a message

Debug a delivery

history is the one to reach for first. It returns each event in the send with the status reason, which is what tells you whether a message was never routed, was rejected by the provider, or was delivered and never opened. content shows what actually rendered, which separates a template bug from a delivery one.

Send to a list

Send in bulk

Four calls in order. The job holds the recipients, and nothing sends until you run it.
Add users in batches rather than one call per recipient. retrieve-job reports progress, and courier bulk list-users <job_id> shows the per-recipient outcome once it has run.

Manage templates

A write leaves a draft. publish is what makes it live, and a send resolves the published version, so a content change nothing published reaches no recipient.

Manage tenants

Manage preferences

Send hasCustomRouting and the full customRouting array together, because the write replaces the topic’s routing rather than merging into it.

Global flags

Every command takes these.

Use it in CI

Pass the key from your secret store and read json rather than the human format, which is not a stable contract.
The CLI exits non-zero on an API error, so a failed send fails the step without extra handling. Use --transform to pull one field out for a later step rather than parsing the whole body.