Webhook events and payloads
All 21 events — messages, contacts, flows, broadcasts, templates and Click-to-WhatsApp leads — with the envelope and example payloads.
Events
Messages
| Event | Fires when |
|---|---|
message.received | A contact sent you a message |
message.sent | WhatsApp accepted a message you sent |
message.delivered | Your message reached the contact’s phone |
message.read | The contact read your message |
message.failed | Your message couldn’t be delivered — includes WhatsApp’s error code and reason |
message.status_updated | Any delivery status change (older catch-all — prefer the four above) |
conversation.created | A new conversation was opened |
Contacts
| Event | Fires when |
|---|---|
contact.created | A contact was added |
contact.updated | A contact’s details changed — includes which fields |
contact.tag_added | A tag was applied |
contact.tag_removed | A tag was removed |
contact.opted_out | A contact replied STOP or was marked opted out |
Flows
| Event | Fires when |
|---|---|
flow.triggered | A flow started for a contact |
flow.completed | A flow finished or handed off to an agent |
flow.failed | A flow hit an error it couldn’t recover from |
flow.exited | A contact left a flow early — timed out or an agent stepped in |
Broadcasts: broadcast.started, broadcast.completed, broadcast.failed
Templates: template.approved, template.rejected (with the reason)
Ads: ad_lead.received — someone messaged you from a Click-to-WhatsApp ad
Contact, template, broadcast, flow and ad-lead events fire however the change was made — the inbox, an import, an automation, the API or Meta.
The envelope
{
"id": "evt_4f1c9a0b2e7d4c3a8b6e5f1d2c3b4a59",
"type": "contact.tag_added",
"workspace_id": "6b2f…",
"created_at": "2026-09-14T10:30:00.000Z",
"api_version": "2026-09-01",
"data": { }
}
idis unique and stable — a retry or resend has the same id. Store handled ids and skip repeats.- Events can arrive more than once and out of order. Use
created_atand your own dedupe.
data by event
// message.received
{ "conversation_id": "…", "contact_id": "…", "whatsapp_message_id": "wamid.…",
"content_type": "text", "text": "Hi, is this still available?" }
// message.sent | message.delivered | message.read | message.failed
{ "whatsapp_message_id": "wamid.…", "conversation_id": "…", // null for a broadcast send
"contact_id": "…", "broadcast_id": null, // set for a broadcast send
"status": "failed", "occurred_at": "2026-09-14T10:30:02.000Z",
"error": { "code": 131026, "title": "Message undeliverable", // message.failed only
"message": "(#131026) Message undeliverable" } }
// contact.created | contact.opted_out
{ "contact": { "id": "…", "phone": "+14155550123", "name": "Asha", "email": null,
"company": null, "opted_out": false, "opted_out_at": null,
"created_at": "…", "updated_at": "…" },
"source": "stop_keyword" } // contact.opted_out only
// contact.updated
{ "contact": { … }, "changed": ["name", "email"] }
// contact.tag_added | contact.tag_removed
{ "contact": { … }, "tag": { "id": "…", "name": "Hot lead" } }
// flow.*
{ "flow_run": { "id": "…", "flow_id": "…", "contact_id": "…", "conversation_id": "…",
"status": "handed_off", "node_key": "ask_budget", "end_reason": null,
"started_at": "…", "ended_at": "…" } }
// broadcast.*
{ "broadcast": { "id": "…", "name": "Diwali offer", "template_name": "diwali_2026",
"status": "sent", "total_recipients": 1200, "sent_count": 1180,
"delivered_count": 1102, "read_count": 640, "failed_count": 20 } }
// template.approved | template.rejected
{ "template": { "id": "…", "name": "order_update", "language": "en_US",
"category": "UTILITY", "status": "REJECTED",
"rejection_reason": "INVALID_FORMAT" } }
// ad_lead.received
{ "contact": { … }, "conversation_id": "…",
"referral": { "ctwa_clid": "ARAkL…", "source_id": "120211…", "source_type": "ad",
"source_url": "https://fb.me/…", "headline": "Book a free demo",
"body": "…", "media_type": "image" },
"whatsapp_message_id": "wamid.…", "occurred_at": "…" }
source_id is the Meta ad ID and ctwa_clid is Meta’s click ID — present only when Ads attribution is on.
Headers
| Header | Value |
|---|---|
X-Vatli-Signature | t=<unix seconds>,v1=<hex HMAC-SHA256> |
X-Vatli-Event-Id | The event’s id |
X-Vatli-Event | The event’s type |
X-Vatli-Webhook-Id | Which of your endpoints it was sent to |
X-Vatli-Delivery-Id | This delivery |
X-Vatli-Delivery-Attempt | 1, then 2, 3… on retries |