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:
| Status | Meaning |
|---|---|
scheduled | Accepted with a future sendAt; waiting to fire. |
queued | Waiting for delivery — the state a broadcast's per-recipient sends pass through. An immediate single send never returns queued. |
sent | The message left Dairo. Confirmation from the recipient's mail server arrives as a Delivery event. |
bounced | A terminal negative signal landed — a bounce stamps bouncedAt, a spam complaint stamps complainedAt. |
failed | The send could not be completed; error carries the reason. Includes a scheduled send that failed its fire-time re-check. |
canceled | A 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.
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.
Event fields
Each event says what happened, to whom, and when.
| Field | Meaning |
|---|---|
type | The delivery event: Send, Delivery, DeliveryDelay, Bounce, Complaint, Reject, or Rendering Failure. |
recipient | The affected address. |
occurredAt | When the event happened at the recipient's mail server. |
bounceType | Permanent, Transient, or Undetermined. |
bounceSubType | A finer classification, e.g. General or MailboxFull. |
diagnosticCode | The reason the receiving mail server gave for a bounce. |
complaintFeedbackType | The kind of complaint, e.g. abuse or fraud. |
agentHint | On 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
| Signal | What it means | What 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. |
Complaint | The 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
- Land in the inbox — cut bounces and complaints at the source.
- Audiences & broadcasts — track a fan-out per recipient.
- API reference — every messages endpoint, with copy-paste requests.