Webhook Payloads
1. Chat Message Payload
This payload is received whenever a new message arrives on your WhatsApp Business Account. The shape of the message object changes depending on what kind of message the customer sent (text, image, video, a button/list tap, a reaction, and so on) — see the sections below for every type.
Every incoming message includes these common fields inside message, no matter the type:
| Field | Description |
|---|---|
conversation_id | WappCloud’s internal ID for the conversation this message belongs to. |
timestamp | Unix timestamp of when the message was sent. |
type | The kind of message received (text, image, video, audio, document, sticker, location, contacts, interactive, reaction, etc.). |
reply_to_message_id | Present only when this message is a reply to one of your earlier messages (the customer tapped “reply” on WhatsApp). Contains the ID of the message being replied to. Omitted entirely when the message is not a reply. |
media_url | Present only for media messages (image, video, audio, document, sticker). A permanent link to WappCloud’s own hosted copy of the file. See the callout below — use this field, not the one inside the type-specific object. |
file_size | Present only for media messages. The file size in bytes (a number). |
Important — which media link should you use?
Media messages carry two different links:
- The link inside the type-specific object (e.g.
message.image.url) is a temporary link from WhatsApp. It expires after a short time and is not accessible if you try to fetch it later.message.media_urlis WappCloud’s own permanently hosted copy of the same file (stored on our servers). This link does not expire.If you need to download, store, or process the media file at any point after receiving the webhook, always use
message.media_url, not the link inside the type-specific object.
Text message
Triggered when the customer sends a plain text message.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "68f1f14a7c8e981501051fca",
"timestamp": "1760686408",
"type": "text",
"text": {
"body": "Welcome"
}
}
}Reply to an earlier message
Same as above, but the customer replied directly to one of your previous messages. Notice the extra reply_to_message_id field — it is only ever present when the message is a reply, and left out otherwise.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "68f1f14a7c8e981501051fca",
"reply_to_message_id": "68f1f14a7c8e981501051fbb",
"timestamp": "1760686408",
"type": "text",
"text": {
"body": "Yes, that works for me"
}
}
}Image message
Triggered when the customer sends a photo. The image object’s mime_type, sha256, id, caption (if the customer added one), and url come from WhatsApp directly — url is temporary. The media_url and file_size fields, at the top level of message, are WappCloud’s permanent hosted copy and its size.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654488",
"type": "image",
"image": {
"mime_type": "image/jpeg",
"sha256": "3b2f...",
"id": "1123456789012345",
"caption": "Here's my order",
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/..."
},
"media_url": "https://wappcloudaws.s3.us-east-1.amazonaws.com/.../chat_messages/...",
"file_size": 77184
}
}Video message
Triggered when the customer sends a video.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654489",
"type": "video",
"video": {
"mime_type": "video/mp4",
"sha256": "9af1...",
"caption": "Quick clip",
"id": "1123456789012346",
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/..."
},
"media_url": "https://wappcloudaws.s3.us-east-1.amazonaws.com/.../chat_messages/...",
"file_size": 2457600
}
}Audio message
Triggered when the customer sends an audio clip or voice note.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654490",
"type": "audio",
"audio": {
"mime_type": "audio/ogg; codecs=opus",
"sha256": "77bc...",
"id": "1123456789012347",
"voice": true,
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/..."
},
"media_url": "https://wappcloudaws.s3.us-east-1.amazonaws.com/.../chat_messages/...",
"file_size": 30512
}
}Document message
Triggered when the customer sends a file such as a PDF, spreadsheet, or Word document.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654491",
"type": "document",
"document": {
"filename": "invoice.pdf",
"mime_type": "application/pdf",
"sha256": "c41d...",
"id": "1123456789012348",
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/..."
},
"media_url": "https://wappcloudaws.s3.us-east-1.amazonaws.com/.../chat_messages/...",
"file_size": 154892
}
}Sticker message
Triggered when the customer sends a sticker.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654492",
"type": "sticker",
"sticker": {
"mime_type": "image/webp",
"sha256": "e910...",
"id": "1123456789012349",
"animated": false,
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/..."
},
"media_url": "https://wappcloudaws.s3.us-east-1.amazonaws.com/.../chat_messages/...",
"file_size": 9820
}
}Sticker, image, video, audio, and document messages all follow the same pattern: a type-specific object with WhatsApp’s own (temporary) fields, plus
media_urlandfile_sizeat the top level ofmessagefor WappCloud’s permanent copy.
Location message
Triggered when the customer shares their location. There is no media file involved, so media_url and file_size are not present.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654493",
"type": "location",
"location": {
"latitude": 12.9715987,
"longitude": 77.5945627,
"name": "WappCloud HQ",
"address": "Bengaluru, Karnataka, India"
}
}
}Contact card message
Triggered when the customer shares one or more saved contacts.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654494",
"type": "contacts",
"contacts": [
{
"name": { "formatted_name": "John Doe", "first_name": "John", "last_name": "Doe" },
"phones": [{ "phone": "+9199xxxxxx", "type": "CELL" }]
}
]
}
}Reaction message
Triggered when the customer reacts to one of your messages with an emoji.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"timestamp": "1787654495",
"type": "reaction",
"reaction": {
"message_id": "wamid.HBgLMTY...",
"emoji": "👍"
}
}
}Interactive reply — button tap (from a list/button message you sent)
Triggered when the customer taps a button inside an interactive message (for example, one sent from a chatbot flow that used buttons).
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"reply_to_message_id": "6a8d715e28b7191dff5eb500",
"timestamp": "1787654496",
"type": "interactive",
"interactive": {
"type": "button_reply",
"button_reply": {
"id": "confirm_order",
"title": "Confirm Order"
}
}
}
}Interactive reply — list item tap (from a list/button message you sent)
Triggered when the customer picks an option from an interactive list message. Notice list_reply also carries an optional description, which button_reply does not have.
{
"messaging_product": "whatsapp",
"message_type": "incoming_message",
"participants": {
"sender": { "from": "9199xxxxxx", "profile": { "name": "Bharath" } },
"receiver": { "to": "9188xxxxxx" }
},
"message": {
"conversation_id": "6a8d715e28b7191dff5eb529",
"reply_to_message_id": "6a8d715e28b7191dff5eb501",
"timestamp": "1787654497",
"type": "interactive",
"interactive": {
"type": "list_reply",
"list_reply": {
"id": "plan_pro",
"title": "Pro Plan",
"description": "Best for growing teams"
}
}
}
}2. Status Update Payload (Delivered)
This payload is received when a message status is updated to ‘delivered’.
{
"messaging_product": "whatsapp",
"message_type": "status_update",
"participants": {
"sender": {
"from": "9199xxxxxx",
"profile": {
"name": "Bharath"
}
},
"receiver": {
"to": "9188xxxxxx"
}
},
"statuses": [
{
"conversation_id": "68f1f505d3e5e42af8bfa3a0",
"message_uid": "25c881167f2d4e7f",
"status": "delivered",
"timestamp": "1760687366",
"meta_pricing": {
"meta_billable": false,
"meta_category": "utility",
"meta_type": "free_customer_service"
}
}
]
}status reflects the delivery stage of the message and will be one of sent, delivered, read, or failed.
meta_pricing describes how WhatsApp is billing (or not billing) the message:
| Field | Description |
|---|---|
meta_billable | Whether WhatsApp charges for this message. |
meta_category | The conversation category WhatsApp assigned, e.g. marketing, utility, authentication, service, or free_customer_service/free_entry_point for non-billable conversations. |
meta_type | Additional pricing type detail supplied by WhatsApp. |
Since these values are set directly by WhatsApp, the exact strings you receive can evolve as WhatsApp changes its pricing model — treat meta_category/meta_type as informational text rather than a fixed list.
3. Status Update Payload (Failed)
This payload is received when a message fails to be delivered.
{
"messaging_product": "whatsapp",
"message_type": "status_update",
"participants": {
"sender": {
"from": "9199xxxxxx",
"profile": {
"name": "Bharath"
}
},
"receiver": {
"to": "9188xxxxxx"
}
},
"statuses": [
{
"conversation_id": "68f3195eb1aac372397c1c38",
"status": "failed",
"timestamp": "1760762206",
"errors": [
{
"code": 131026,
"title": "Message undeliverable",
"message": "Message undeliverable",
"error_data": {
"details": "Message Undeliverable."
}
}
],
"meta_pricing": {
"meta_billable": false,
"meta_category": "",
"meta_type": ""
}
}
]
}errors is only present on failed statuses and lists the reason(s) WhatsApp gave for the failure.
4. Button Reply Webhook Payload
This webhook is triggered specifically when a user taps a quick reply button on a message that was sent through the External API (as opposed to a button/list sent from a chatbot flow, which arrives via the Chat Message Payload’s interactive type described in section 1).
If you send a message through the External API and the message contains reply buttons, WappCloud will send this webhook when the recipient taps one of the buttons.
{
"messaging_product": "whatsapp",
"message_type": "api_button_reply",
"participants": {
"sender": {
"from": "9188xxxxxx",
"profile": {
"name": "Gon"
}
},
"receiver": {
"to": "9188xxxxxx"
}
},
"reply": {
"message_uid": "d3a26e24684f4a4a",
"timestamp": "1780555785",
"type": "button",
"text": "Products view"
}
}Note: All timestamps are in Unix timestamp format.