Message Events
Events fired across the lifecycle of a message. Every delivery uses the common envelope and headers described on the overview page.
message.received
Fired when a new incoming message arrives from a customer on any channel.
Payload
{
"event": "message.received",
"timestamp": "2026-05-16T12:00:00.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI0",
"from": "+918245678901",
"contact_name": "John Doe",
"type": "text",
"content": {
"text": "Hi, I need help with my order"
},
"timestamp": "2026-05-16T12:00:00Z"
}
}
Content variations by message type
Text message:
{
"type": "text",
"content": {
"text": "Hello, can you help me?"
}
}
Image message:
{
"type": "image",
"content": {
"image": {
"id": "media-id-123",
"mime_type": "image/jpeg",
"caption": "Here is the damaged product"
}
}
}
Document message:
{
"type": "document",
"content": {
"document": {
"id": "media-id-456",
"mime_type": "application/pdf",
"filename": "invoice.pdf"
}
}
}
Audio message:
{
"type": "audio",
"content": {
"audio": {
"id": "media-id-789",
"mime_type": "audio/ogg"
}
}
}
Video message:
{
"type": "video",
"content": {
"video": {
"id": "media-id-012",
"mime_type": "video/mp4"
}
}
}
Location message:
{
"type": "location",
"content": {
"location": {
"latitude": 25.2048,
"longitude": 55.2708,
"name": "Dubai Mall",
"address": "Financial Centre Rd, Dubai"
}
}
}
Interactive button reply:
{
"type": "interactive",
"content": {
"interactive": {
"type": "button_reply",
"button_reply": {
"id": "btn_yes",
"title": "Yes, confirm"
}
}
}
}
Interactive list reply:
{
"type": "interactive",
"content": {
"interactive": {
"type": "list_reply",
"list_reply": {
"id": "product_123",
"title": "Red T-Shirt",
"description": "Cotton, Size M"
}
}
}
}
Example: handling in Node.js
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
if (event === 'message.received') {
console.log(`New message from ${data.contact_name} (${data.from})`);
console.log(`Type: ${data.type}`);
if (data.type === 'text') {
console.log(`Text: ${data.content.text}`);
}
// Process the message...
}
res.status(200).send('OK');
});
message.sent
Fired when a message is sent to a customer - either by a human agent, AI agent, or via the API.
Payload
{
"event": "message.sent",
"timestamp": "2026-05-16T12:00:05.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI1",
"to": "+918245678901",
"type": "text",
"content": {
"text": "Hi John! I'd be happy to help you with your order. Could you share your order number?"
},
"status": "sent",
"timestamp": "2026-05-16T12:00:05.000Z",
"sender_id": "agent-uuid-or-null",
"is_ai": true,
"agent_id": "ai-agent-uuid"
}
}
Fields
| Field | Type | Description |
|---|---|---|
message_id | string | Platform message ID |
to | string | Recipient identifier (phone number, PSID, etc.) |
type | string | text, image, template, interactive, etc. |
content | object | Message content (varies by type) |
status | string | sent |
timestamp | string | ISO 8601 timestamp |
sender_id | string|null | User ID of the human agent who sent it, or null |
is_ai | boolean | true if sent by an AI agent (only present on AI replies) |
agent_id | string | AI agent ID (only present on AI replies) |
channel | string | whatsapp, instagram, or messenger (present on Instagram/Messenger) |
Template message example
{
"event": "message.sent",
"timestamp": "2026-05-16T14:30:00.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI2",
"to": "+918245678901",
"type": "template",
"content": {
"template": {
"name": "order_shipped",
"language": "en",
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "John" },
{ "type": "text", "text": "ORD-78901" }
]
}
]
}
},
"status": "sent",
"timestamp": "2026-05-16T14:30:00.000Z",
"sender_id": "user-uuid"
}
}
message.delivered
Fired when a sent message is delivered to the recipient's device.
Payload
{
"event": "message.delivered",
"timestamp": "2026-05-16T12:00:08.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI1",
"status": "delivered",
"timestamp": "2026-05-16T12:00:08Z",
"recipient_id": "+918245678901"
}
}
message.read
Fired when the recipient reads the message (blue double-check on WhatsApp).
Payload
{
"event": "message.read",
"timestamp": "2026-05-16T12:01:15.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI1",
"status": "read",
"timestamp": "2026-05-16T12:01:15Z",
"recipient_id": "+918245678901"
}
}
message.failed
Fired when a message fails to deliver.
Payload
{
"event": "message.failed",
"timestamp": "2026-05-16T12:00:10.000Z",
"webhook_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"message_id": "wamid.HBgNOTE4MjQ1Njc4OTAxFQIAERgSQzI3",
"status": "failed",
"timestamp": "2026-05-16T12:00:10Z",
"recipient_id": "+918245678901",
"error": {
"code": 131047,
"message": "Re-engagement message - Message failed to send because more than 24 hours have passed since the customer last replied to this number"
}
}
}
Common error codes
| Code | Description |
|---|---|
131047 | Outside 24-hour conversation window |
131026 | Message undeliverable (blocked or phone off) |
131051 | Unsupported message type |
131053 | Media download failed |
130472 | Rate limit exceeded |