> ## Documentation Index
> Fetch the complete documentation index at: https://docs.senderkit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Messages

> The durable record of every send, its status, and its history.

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](/concepts/sending), the message is how you find out whether delivery
actually succeeded.

## The message lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> queued
    [*] --> scheduled
    scheduled --> queued
    scheduled --> canceled
    queued --> rendered
    queued --> canceled
    queued --> blocked
    rendered --> sent
    rendered --> blocked
    sent --> delivered
    sent --> failed
    sent --> opted_out
    queued --> opted_out
    queued --> failed
    rendered --> failed
```

| Status      | What it means                                  | What triggers it                                                                                                                                                                                                            |
| ----------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scheduled` | Accepted but holding until `scheduledAt`       | A `send()` with a future `scheduledAt`                                                                                                                                                                                      |
| `queued`    | Accepted and ready to dispatch                 | The `send()` call, or a scheduled message reaching its fire time                                                                                                                                                            |
| `rendered`  | Template + variables resolved                  | Background dispatcher                                                                                                                                                                                                       |
| `sent`      | A provider accepted the message                | Successful provider dispatch                                                                                                                                                                                                |
| `delivered` | The provider confirmed delivery                | Provider webhook                                                                                                                                                                                                            |
| `failed`    | Delivery failed                                | Provider webhook, a config error, or retries exhausted                                                                                                                                                                      |
| `opted_out` | Recipient is unsubscribed/suppressed           | Provider webhook, one-click unsubscribe link, or send skipped because the recipient previously opted out                                                                                                                    |
| `blocked`   | Delivery halted by outbound abuse detection    | Phishing scan flagged the content with high confidence; the message is never handed to a provider. The message timeline records a generic notice; detection details are operator-only and not exposed via the customer API. |
| `canceled`  | Delivery intentionally stopped before dispatch | `messages.cancel()` or the dashboard cancel action                                                                                                                                                                          |

<Note>
  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."
</Note>

In [test mode](/concepts/environments), 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`:

```ts theme={null}
const { data, nextCursor } = await senderkit.messages.list({
  status: "failed",
  channel: "email",
});
```

The API also supports a live tail (a Server-Sent Events stream) for watching sends in
real time. See the [API Reference](/api-reference/introduction), the
[TypeScript SDK](/sdks/typescript), and the [CLI](/cli/messages) for the full surface.

<Tip>
  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.
</Tip>

## 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](/webhooks)
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:

| Plan    | Retention |
| ------- | --------- |
| Free    | 3 days    |
| Starter | 30 days   |
| Pro     | 90 days   |

<Warning>
  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.
</Warning>

<CardGroup cols={2}>
  <Card title="Sending" icon="paper-plane" href="/concepts/sending">
    How a message gets created and dispatched.
  </Card>

  <Card title="Channels & Providers" icon="tower-broadcast" href="/concepts/channels-and-providers">
    Who delivered the message and how failures surface.
  </Card>
</CardGroup>
