WhatsApp events
Every WhatsApp message emits events as it moves through its lifecycle. Each event is a stamped fact about the message: when Bird accepted it, when it reached WhatsApp, when it was delivered, when the recipient read it, or that it failed. Events are how you follow what happened to a message after the send returns 202.
The event envelope
Events reach you in two shapes that carry the same lifecycle facts. A webhook delivery is the standard envelope described in the Webhooks guide: a type, a timestamp, and a type-specific data object.
Exemplo de código
{
"data": {
"direction": "outbound",
"from": { "phone_number": "+13124495569" },
"metadata": { "session_id": "sess_4821" },
"tags": [{ "name": "flow", "value": "login-otp" }],
"to": { "phone_number": "+14155550100" },
"whatsapp_id": "wam_01ky7qbvswf3fvyaw3az90391c",
"workspace_id": "ws_01ky7m235keycbnwyajabe1a6b"
},
"timestamp": "2026-07-23T14:51:39.913Z",
"type": "whatsapp.delivered"
}Every whatsapp.* payload's data carries the identity base: whatsapp_id, workspace_id, the message direction (outbound for messages you send), the from and to addresses (each a phone_number in E.164 and/or a Meta business-scoped user ID bsuid), and the tags and metadata from the send request (both null when the message carried none).
The events API returns the same lifecycle as leaner records: each event is an id, a type, and the occurred_at timestamp, since the message identity is already fixed by the request URL.
Lifecycle events
A message emits events in order as it progresses. Not every message emits every type: a failed send stops at whatsapp.failed, and whatsapp.read only appears if the recipient opens the message.
| Event | Meaning |
|---|---|
| whatsapp.accepted | Bird accepted the send request. This is what the 202 reported. |
| whatsapp.sent | Handed to the WhatsApp network. |
| whatsapp.delivered | Delivery confirmed to the recipient's device. |
| whatsapp.read | The recipient opened the message. |
One thing about whatsapp.read: it does not change the message status. A delivered message stays delivered, and the read is recorded as a read_at timestamp on the message alongside the event.
The event type list is open: new types may be added over time, so treat an unrecognized value as a future event rather than an error.
Failure events
whatsapp.failed is terminal: the message will not be delivered, and no further events follow. It is the one event type that carries an error object with the failure detail: a Bird-stable code (for example undeliverable or insufficient_balance), a human-readable description, an optional raw meta_error_code from the WhatsApp Cloud API, and the failure's occurred_at. The same object appears on the API record and in the webhook payload, and is absent on every other event type.
Reading events from the API
GET /v1/whatsapp/messages/{message_id}/events returns a message's events in chronological order. The timeline is bounded and returned in full, so the list is not paginated. Reading events needs an API key with the whatsapp_messages scope:
Exemplo de código
curl https://us1.platform.bird.com/v1/whatsapp/messages/wam_.../events \
-H "Authorization: Bearer $BIRD_API_KEY"A message that was accepted, sent, delivered, and read returns four events:
Exemplo de código
{
"data": [
{
"id": "ev_01ky7q6a1fejfbvs0myn41hj41",
"occurred_at": "2026-07-23T14:48:34.71Z",
"type": "whatsapp.accepted"
},
{
"id": "ev_01ky7q6a2denvtd6jg1vqwmg13",
"occurred_at": "2026-07-23T14:48:35.671Z",
"type": "whatsapp.sent"
},
{
"id": "ev_01ky7q6a2zff9r2qm74mmg1g6z",
"occurred_at": "2026-07-23T14:48:36.642Z",
"type": "whatsapp.delivered"
},
{
"id": "ev_01ky7q6c21frssf0vj8h50qysw",
"occurred_at": "2026-07-23T14:48:38.65Z",
"type": "whatsapp.read"
}
]
}To keep only one type, pass the type query parameter (for example ?type=whatsapp.failed); omit it for the full timeline.
The same timeline is what the WhatsApp log page renders when you open a message.

Webhooks
The same five lifecycle events are delivered to your endpoints as webhooks, so you can react to a message the moment it moves instead of polling the events API. Subscribe an endpoint to any whatsapp.* type from the Webhooks page in the dashboard or through the webhooks API; each delivery uses the event envelope with the identity base and, on whatsapp.failed, the error object. The Webhooks guide covers creating endpoints, verifying signatures, and retries.
Next steps
- WhatsApp log: the per-message view that renders this timeline
- Sending WhatsApp messages: where a message's lifecycle begins
- Webhooks guide: endpoints, signatures, retries, and the full event catalog