Skip to main content
Every send creates a message — the record of truth for what SenderKit did with it. A message captures the recipient, the channel, the variables, which provider handled it, and a timeline of everything that happened. Because sending is asynchronous, the message is how you find out whether delivery actually succeeded.

The message lifecycle

The status enum also includes dispatched. In the current pipeline a message moves queued → rendered → sent, and the moment a provider accepts it is recorded as a dispatched event on the message’s timeline while the status itself becomes sent. Read sent as “handed to the provider.”
opted_out reflects only a send skipped before dispatch because the recipient had already opted out. If a recipient unsubscribes or complains after a message reached a terminal outcome (delivered or failed), that outcome is unchanged — the unsubscribe/complaint is recorded and reported via webhook events, but it no longer overwrites a delivery result that already happened.
In test mode, SenderKit synthesizes this lifecycle (rendered → sent → delivered) without calling a provider, so your logs look the same as live without anything leaving the building.

Querying messages

List messages newest-first with cursor pagination, and filter by status, channel, template, or your own metadata:
The API also supports a live tail (a Server-Sent Events stream) for watching sends in real time. See the API Reference, the TypeScript SDK, and the CLI for the full surface.
Attach metadata (e.g. { userId: "usr_123", orderId: "ord_9" }) when you send. It’s indexed, so you can later filter messages down to a single user or order.

Engagement (opens & clicks)

For email, SenderKit also records provider-reported opens and link clicks as openedAt / clickedAt on the message — each set once, on the first occurrence. These are engagement signals, not lifecycle states: they never change a message’s status, and delivered remains the terminal happy-path status regardless of whether the recipient later opens it or clicks a link. Subscribe to the message.opened / message.clicked webhook events to be notified as they happen, or read the fields directly via messages.get/messages.list.

Retention

Messages are retained for a limited window and then deleted:
Don’t treat SenderKit as your long-term audit log. If you need history beyond your plan’s retention window, export or persist messages in your own system, and use metadata to correlate them with your records.

Sending

How a message gets created and dispatched.

Channels & Providers

Who delivered the message and how failures surface.