Skip to main content
Every event arrives as { "type": "...", "data": {...} }. Branch on type, and ignore types you don’t recognize, since Courier may add new ones.

Message events

message:updated

Fires every time a message changes status. data is the same object the endpoint returns, including any metadata you sent (trace_id, tags, event, utm). Timestamps accumulate as the message moves along, so a CLICKED event still carries enqueued, sent, delivered, and opened. A DELIVERED event:
What each status adds to data: DELIVERED comes from your provider and OPENED and CLICKED come from Courier’s tracking, so engagement events can arrive before the delivery event, or without it. See .

Template events

Use these to connect a translation management system or a custom approval workflow.

notification:submitted

Fires when a template is submitted for review and hasn’t been published yet. submission_id is the submission’s timestamp.

notification:submission_canceled

Fires when a pending submission is canceled before it’s published.

notification:published

Fires when a template is published, either directly or when an approved submission publishes. Listen for this one to sync template content to another system.

Audience events

audiences:created, audiences:updated, and audiences:deleted fire when an audience is created, changed, or deleted. An audiences:updated event:

audiences:calculated

Fires when Courier finishes recalculating an audience’s membership. This runs every time an audience is created or updated, and takes longer the more users your workspace has.

audiences:user:matched

Fires when a user starts matching an audience’s filter, usually because their profile was created or updated. It’s the same event behind the journey audience trigger, so you can react to it with a webhook or by starting a journey.

audiences:user:unmatched

Fires when a user stops matching an audience’s filter, because their profile changed or was deleted.

Preference events

preferences:user:updated

Fires when a user changes their subscription preference for a topic, whether they change it on the hosted preferences page, unsubscribe link, or through the API. One event covers every kind of change: opting in, opting out, and editing which channels a topic uses. data describes a single change to a single topic.
custom_routing lists the channels a user picked for the topic and is empty unless has_custom_routing is true. tenant_id is absent when the change wasn’t made in a tenant. previous is absent when the earlier state isn’t known, such as the first time a user changes their preference for a topic.

Limits & behavior

  • One message produces several events. message:updated fires on every status change, so key your handler on data.id and data.status.
  • data.id identifies the resource, not the event. Retries and status changes can share it.
  • No timestamp in the body. The send time is on the courier-signature header.

FAQ

One per status change. A delivered and opened email produces at least four message:updated events: enqueued, sent, delivered, and opened.
data on message:updated carries the metadata from your send, including trace_id, tags, event, and utm.