Event Overview
Three events cover every message that passes through a conversation. They share one payload shape, so a single handler works for all of them.
Method:
POSTContent-Type:
application/json
The split between
message_sent and template_sent is deliberate: a campaign integration usually wants template sends without every conversational reply alongside them. A template fires template_sent only — it does not also fire message_sent.Payload Structure
Field Descriptions
About status
status here is the state at the moment the message was stored — sent for an accepted outbound message, failed for a rejected one, and read for anything inbound (you are reading it, by definition). It is not the final state of an outbound message.
To follow a message to
delivered or read, subscribe to message_status_updated.
A failed send still fires
message_sent or template_sent, with status set to the failure and msg_id empty. That is intentional — a rejected send is something you want to know about, not something that silently disappears. Check status before treating a message_sent as a success.What never fires
- Internal records —
developernotes, chat-reset markers and link-click records are not messages anyone sent - Test conversations — the Test Chat tab does not deliver real messages, so it does not fire real webhooks
call_endedon a chat agent’s webhook — see Introduction
Example Implementation
Node.js (Express)
Python (FastAPI)
Related
Delivery Status
Follow a message to delivered and read
Get WhatsApp Messages
Pull conversation history over the API instead