Track delivery

Follow every send by its id — read its current status, list its per-recipient delivery events, and react to bounces and complaints.

Every email you send leaves a timeline. Read a send's current status with the id the send call returned, list its per-recipient delivery events, or have the same signals pushed to your app as they happen.

The lifecycle

A send's status tells you where it stands right now:

StatusMeaning
scheduledAccepted with a future sendAt; waiting to fire.
queuedWaiting for delivery — the state a broadcast's per-recipient sends pass through. An immediate single send never returns queued.
sentThe message left Dairo. Confirmation from the recipient's mail server arrives as a Delivery event.
bouncedA terminal negative signal landed — a bounce stamps bouncedAt, a spam complaint stamps complainedAt.
failedThe send could not be completed; error carries the reason. Includes a scheduled send that failed its fire-time re-check.
canceledA scheduled send you canceled before it fired.

Delivery confirmations do not change status — they are recorded as events and advance the send's lastEventType and lastEventAt fields, so a sent message with lastEventType: "Delivery" has been accepted by the recipient's mail server.

Read a send

Fetch a send with GET /v1/messages/{messageId} (scope messages:read), using the id returned when you sent it.

curl https://api.dairo.app/v1/messages/msg_3fa85f64 \
  -H "Authorization: Bearer $DAIRO_API_KEY"
{
  "object": "message",
  "id": "msg_3fa85f64",
  "inboxId": "inbox_7c9e6679",
  "channel": "email",
  "from": "receipts@yourapp.com",
  "to": ["nobody@example.com"],
  "subject": "Your receipt",
  "status": "bounced",
  "sentAt": "2026-06-12T11:59:58Z",
  "providerMessageId": "msg_pm_9f8c2a1b4e7d",
  "error": null,
  "lastEventType": "Bounce",
  "lastEventAt": "2026-06-12T12:00:00Z",
  "bouncedAt": "2026-06-12T12:00:00Z",
  "complainedAt": null,
  "scheduledAt": null,
  "canceledAt": null,
  "createdAt": "2026-06-12T11:59:57Z",
  "events": [
    { "object": "message_event", "eventId": "evt_9d2b", "type": "Bounce", "recipient": "nobody@example.com", "bounceType": "Permanent", "occurredAt": "2026-06-12T12:00:00Z" }
  ]
}

The send carries its delivery events inline, newest first.

List the delivery events

For the full timeline, list one send's delivery events with GET /v1/messages/{messageId}/events: newest first, 50 by default, up to 100 with limit. The list comes back in one page.

curl "https://api.dairo.app/v1/messages/msg_3fa85f64/events?limit=50" \
  -H "Authorization: Bearer $DAIRO_API_KEY"
{
  "object": "list",
  "data": [
    { "object": "message_event", "eventId": "evt_9d2b", "messageId": "msg_3fa85f64", "type": "Bounce", "recipient": "nobody@example.com", "bounceType": "Permanent", "occurredAt": "2026-06-12T12:00:00Z" },
    { "object": "message_event", "eventId": "evt_5c1a", "messageId": "msg_3fa85f64", "type": "Send", "recipient": "nobody@example.com", "occurredAt": "2026-06-12T11:59:58Z" }
  ],
  "pagination": { "nextCursor": null, "hasMore": false }
}

Event fields

Each event says what happened, to whom, and when.

FieldMeaning
typeThe delivery event: Send, Delivery, DeliveryDelay, Bounce, Complaint, Reject, or Rendering Failure.
recipientThe affected address.
occurredAtWhen the event happened at the recipient's mail server.
bounceTypePermanent, Transient, or Undetermined.
bounceSubTypeA finer classification, e.g. General or MailboxFull.
diagnosticCodeThe reason the receiving mail server gave for a bounce.
complaintFeedbackTypeThe kind of complaint, e.g. abuse or fraud.
agentHintOn bounce and complaint events, a short machine-readable recommendation for what to do next.

Events can arrive out of order. Sort by occurredAt — not by when you received each event — when you reconstruct a message's lifecycle.

What to do with each signal

SignalWhat it meansWhat to do
Bounce with bounceType: "Permanent"The address doesn't exist or refuses mail.Take it off your lists. Dairo blocks future sends to that address for you — repeated hard bounces hurt your reputation and push future mail toward spam.
Bounce with bounceType: "Transient"A full mailbox or a temporary server problem.Back off and retry later rather than giving up right away.
ComplaintThe recipient marked your mail as spam — the strongest negative signal there is.Stop contacting them. Dairo blocks future sends to that address for you.

Get events pushed to you

Polling works, but for real-time updates subscribe to message.delivered, message.bounced, and message.complained via webhooks, and Dairo calls your app the moment each one lands. For a single, durable, account-wide stream of everything, read the event ledger.

Next steps

On this page