Skip to main content

WhatsApp

This page describes the inbound (MO) messages and notifications you can receive from WhatsApp users through the CM.com Messaging API. Every inbound WhatsApp event is delivered to your MO webhook as an HTTP request with a JSON body. Use this page to identify each event type, understand its payload and decide how your application should respond.

For the generic behaviour of inbound messages across all channels, see Incoming messages.

Before you begin​

Make sure that:

  • A WhatsApp Business number is connected to your CM.com account.
  • An MO webhook is configured for that number, and your endpoint responds with a 2xx status code.
  • The messageContext field is enabled on your MO webhook. You need this field to correlate replies with the original message. If your payloads do not contain messageContext, contact CM.com Support to have it enabled.
Design for unknown fields

Meta regularly extends the WhatsApp platform. Parse payloads tolerantly: ignore fields you do not recognise and do not fail on null values, so that new attributes do not break your integration.


Payload structure​

All inbound WhatsApp events share the same envelope. Channel-specific data is placed in message.custom.

FieldTypeDescription
referencestringUnique identifier of the inbound message. For WhatsApp messages this is the message ID assigned by Meta (wamid.…). Store it if you need to correlate replies, deletions or errors.
messageContextstringReference of the message the user replied to. Empty when the message is not a reply. See Replies.
from.numberstringPhone number of the WhatsApp user, or their Business-scoped User ID if the phone number is not shared.
from.namestringWhatsApp profile name of the user.
from.whatsappobjectThe user's user_id (Business-scoped User ID), and where applicable parent_user_id and username. See Business-scoped User IDs.
to.numberstringYour WhatsApp Business number that received the message.
message.textstringText content of the message. For button and list replies, this contains the title of the selected option. Empty for media messages: a caption is delivered in message.media.title.
message.mediaobjectMedia details (mediaUri, contentType, title). Populated for media messages only. See Media object.
message.customobjectWhatsApp-specific data. The contents depend on the event type; see Event types.
message.custom.meta_received_timestringTimestamp at which Meta received the message.
message.custom.message_typestringExplicit event type, where provided (for example document, location, contacts or request_welcome).
message.errorstringError description supplied by Meta. Empty unless the message (partially) failed. See Error notifications.
groupingsarrayGrouping values associated with the message.
timestringTime at which CM.com received the message, in local time (Europe/Amsterdam).
timeUtcstringTime at which CM.com received the message, in UTC.
channelstringAlways WhatsApp for the events on this page.

Event types​

Use the table below to determine which kind of event you have received. Check for the indicators in the order listed; the first match identifies the event.

EventHow to identify it
Error notificationmessage.error is not empty
Deleted messagemessage.custom.deletedMessage is present
Location messagemessage.custom.message_type is location
Contact messagemessage.custom.message_type is contacts
Welcome requestmessage.custom.message_type is request_welcome
BSUID changemessage.custom.message_type is system
Interactive template replymessage.custom.button is present
Interactive message replymessage.custom.interactive.type is list_reply or button_reply
Flows replymessage.custom.interactive.type is nfm_reply
Call permission replymessage.custom.interactive.type is call_permission_reply
Product ordermessage.custom.order is present
Ad referralmessage.referral is present
Marketing preference updateSee Marketing preference updates
Media messagemessage.media.mediaUri is not empty
Text messageNone of the above; message.text contains the message

Any message can also be a reply to an earlier message. Check messageContext independently of the event type.


Messages from users​

Media messages​

Inbound media messages follow the same support and restrictions as outbound media. See Media messages for supported formats and size limits.

WhatsApp-specific behaviour:

WhatsApp contentReceived as
GIFVideo file with content type video/mp4
StickerMedia message with content type image/webp

The media file itself is not included in the webhook. Download it from the URL in message.media.mediaUri.

Media object​

FieldTypeDescription
mediaUristringURL from which you can download the file.
contentTypestringMIME type of the file, for example image/jpeg or application/pdf.
titlestringThe caption the user typed with the media. Empty if the user did not add a caption.
The caption is in media.title, not in message.text

When a user sends a file with a caption, the caption is delivered in message.media.title and message.text is empty. media.title does not contain the original file name. Use contentType to determine the file type, and generate your own file name when you store the file.

Document with caption
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUwxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "https://cdn-3.messaging.cm.com/fileproxy/files/39d2aa694f0f474cb1c464e57f26229e",
"contentType": "application/pdf",
"title": "Here is the invoice you asked for."
},
"custom": {
"meta_received_time": "2026-09-29T06:08:25",
"message_type": "document"
}
},
"groupings": ["", "", ""],
"timeUtc": "2026-09-29T06:08:26",
"channel": "WhatsApp"
}

Delete media​

After you have downloaded and stored a media file, you can delete it from CM.com's servers by sending a DELETE request to the exact URL from which you retrieved it (message.media.mediaUri).

Media is hosted on the following server:

  • cdn-eu1.messaging.cm.com

Request

DELETE {mediaUri} HTTP/1.1
Host: cdn-eu1.messaging.cm.com

Response

A successful request returns status code 204 with an empty body. No further action is required.

HTTP/1.1 204 No Content
Deletion is permanent

A deleted media file cannot be recovered. Make sure you have stored the file before you delete it.

Location messages​

Users can share a location with your business. The location is provided in message.custom.location.

Live location is not supported

Only static locations are delivered. Live location updates shared by the user are not forwarded.

FieldTypeRequiredDescription
latitudenumberYesLatitude of the location. Can be negative.
longitudenumberYesLongitude of the location. Can be negative.
labelstringNoName or description of the location.
searchQuerystringNoAddress or search query related to the location.
Location message
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"location": {
"latitude": 51.603802,
"longitude": 4.770821,
"label": "CM HQ",
"searchQuery": "Konijnenberg 30"
},
"meta_received_time": "2024-02-21T11:01:34",
"message_type": "location"
}
},
"groupings": ["", "", ""],
"timeUtc": "2024-02-21T11:01:35",
"channel": "WhatsApp"
}

Contact messages​

Users can share one or more contact cards in a single message. The cards are provided as an array in message.custom.contacts.

The structure follows WhatsApp's contact format. If you are familiar with the vCard (VCF) format or the address book formats used by Android or iOS, the structure will look familiar.

FieldTypeRequiredDescription
nameobjectYesName of the contact (formatted_name, first_name, last_name, middle_name, prefix, suffix).
phonesarrayNoPhone numbers, each with phone, type and, if the number is on WhatsApp, wa_id.
emailsarrayNoEmail addresses of the contact.
addressesarrayNoPostal addresses (street, city, zip, country, country_code, type).
orgobjectNoOrganisation details (company, department, title).
urlsarrayNoWebsites of the contact.
birthdaystringNoBirthday of the contact.
vcardstringNoThe complete contact card as a Base64-encoded vCard.
originstringNoOrigin of the contact card. contact_request when the user shared their own number through a request contact info button.

Optional fields that the user did not fill in are returned as null.

Contact message
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"contacts": [
{
"vcard": "QkVHSU46VkNBUkQKVkVSU0lPTjozLjAKTjpjb207Q007OzsKRk46Q00uY29tCk9SRzpDTS5jb20gRGVtbyAyClRJVExFOgpURUw7dHlwZT1Nb2JpbGU7d2FpZD0zMTc2MjAxMTU3MDorMzEgNzYgMjAxIDE1NzAKWC1XQS1CSVotTkFNRTpDTS5jb20KRU5EOlZDQVJE",
"origin": "other",
"addresses": [
{
"city": "Breda",
"country": "Netherlands",
"country_code": "NL",
"street": "Konijnenberg 30",
"type": "WORK",
"zip": "4825 BD"
}
],
"birthday": null,
"emails": null,
"name": {
"formatted_name": "CM.com",
"first_name": "CM",
"last_name": "com",
"middle_name": null,
"suffix": null,
"prefix": null
},
"org": {
"company": "CM.com",
"department": null,
"title": null
},
"phones": [
{
"phone": "+31 76 201 1570",
"type": "MOBILE",
"wa_id": "31762011570"
}
],
"urls": null
}
],
"meta_received_time": "2026-07-23T09:01:34",
"message_type": "contacts"
}
},
"groupings": ["", "", ""],
"timeUtc": "2026-07-23T09:01:35",
"channel": "WhatsApp"
}

Replies​

On WhatsApp, a user can reply to a specific message. This works both for messages you sent (MT) and for messages the user sent earlier (MO). In both cases, the messageContext field of the inbound message tells you which message was replied to.

User replies to…messageContext contains…
A message you sent (MT)The reference you set when sending that MT message.
One of their own messages (MO)The reference (wamid.…) of that earlier MO message.
Nothing (not a reply)An empty string.
Requires the messageContext field

Without the messageContext field on your MO webhook you cannot tell which message was replied to. See Before you begin.

Replies to your messages (MT)​

To recognise replies to a message you sent, set a reference on the outbound message.

Send request
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "CM.com",
"to": [
{ "number": "0031612345678" }
],
"allowedChannels": ["WhatsApp"],
"reference": "webinar-invite-2026-10",
"body": {
"type": "auto",
"content": "Reply to this message if you want to receive an invitation to our next webinar."
}
}
]
}
}

When the user replies to that message, messageContext contains the reference you set:

Inbound reply
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUIxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "webinar-invite-2026-10",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "I would like an invitation to the webinar.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {}
},
"groupings": ["", "", ""],
"timeUtc": "2026-10-05T08:32:33",
"channel": "WhatsApp"
}
Use unique references

If you reuse the same reference for multiple messages, you cannot tell which of them the user replied to. Use a unique reference per message where you need reply tracking.

Replies to the user's own messages (MO)​

To recognise replies to earlier inbound messages, store the reference of every inbound message you receive. For WhatsApp, this is the message ID assigned by Meta (wamid.…).

The user first sends a message:

Original message
{
"reference": "wamid.HBgLMTY0NjcwNDM1OTUVAgARGBI1RjQyNUE3NEYxMzAzMzQ5MkEA",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "I would like to reserve a table for four, please.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {}
},
"groupings": ["", "", ""],
"timeUtc": "2026-10-05T08:32:33",
"channel": "WhatsApp"
}

The user then replies to that message. The new message has its own reference, and messageContext contains the reference of the original message:

Reply to original message
{
"reference": "wamid.HBgLMzQ2ODUxMjA0NzMVAgASGBYzRUIwOEU5NzhENEIzNkI5MDE2QkE3AA",
"messageContext": "wamid.HBgLMTY0NjcwNDM1OTUVAgARGBI1RjQyNUE3NEYxMzAzMzQ5MkEA",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Scratch that, a friend can't make it. Could you make it a table for three, please?",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {}
},
"groupings": ["", "", ""],
"timeUtc": "2026-10-05T08:35:12",
"channel": "WhatsApp"
}

Replying to a user's message​

You can also send a message as a reply to a specific message from the user. The user then sees your message quoted against their original message in WhatsApp.

Take the reference of the inbound message:

Inbound message
{
"reference": "wamid.HBgLMzQ2ODUxMjA0NzMVAgASGBYzRUIwOEU5NzhENEIzNkI5MDE2QkE3AA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "I would like an invitation to the webinar.",
"custom": {},
"error": ""
},
"groupings": [],
"time": "2024-09-17 11:37:31",
"timeUtc": "2024-09-17T09:37:31",
"channel": "WhatsApp"
}

Then pass it as context.message_id in the richContent.conversation of your outbound message:

Send request
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "CM.com",
"to": [
{ "number": "0031612345678" }
],
"allowedChannels": ["WhatsApp"],
"reference": "webinar-invite-confirmation",
"body": {
"type": "auto",
"content": "Fallback text"
},
"richContent": {
"conversation": [
{
"text": "Great! We will send you the invitation soon. Thank you for your interest in our webinar.",
"context": {
"message_id": "wamid.HBgLMzQ2ODUxMjA0NzMVAgASGBYzRUIwOEU5NzhENEIzNkI5MDE2QkE3AA=="
}
}
]
}
}
]
}
}

Interactive responses​

Interactive template replies​

When a user taps a button in an interactive template, the inbound message contains a message.custom.button object that identifies the button.

FieldTypeDescription
labelstringText of the button the user tapped.
payloadstringThe payload you assigned to this button when sending the template. Assign a unique payload per button to identify it reliably.

For quick_reply buttons, the button text is also included in message.text.

Template button reply
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUMxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Yes, this is OK",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"button": {
"label": "Yes, this is OK",
"payload": "aGlzIHRoaXMgaXMgY29vZHNhc2phZHdpcXdlMGZoIGFTIEZISUQgV1FEV0RT"
},
"meta_received_time": "2024-02-21T11:01:34"
}
},
"groupings": ["", "", ""],
"timeUtc": "2024-02-21T11:01:35",
"channel": "WhatsApp"
}

Interactive message replies​

Interactive messages are sent within the customer service window and are different from interactive templates. For how to send them, see Interactive messages.

The reply is provided in message.custom.interactive. The type field tells you which kind of interaction took place, and the title of the selected row or button is also included in message.text.

typeTriggered when…ObjectFields
list_replyThe user selects a row in a listlist_replyid, title, description
button_replyThe user taps a reply buttonbutton_replyid, title

The id is the postback ID you assigned to the row or button when sending the message. Use it, rather than the title, to identify the user's choice.

List reply
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "list-row-title",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "list_reply",
"list_reply": {
"id": "your-unique-postback-id",
"title": "list-row-title",
"description": "list-row-description"
},
"button_reply": null
},
"meta_received_time": "2024-02-21T11:01:34"
}
},
"groupings": ["", "", ""],
"timeUtc": "2024-02-21T11:01:35",
"channel": "WhatsApp"
}
Button reply
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "button-title",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "button_reply",
"list_reply": null,
"button_reply": {
"id": "your-unique-postback-id",
"title": "button-title"
}
},
"meta_received_time": "2024-02-21T11:01:34"
}
},
"groupings": ["", "", ""],
"timeUtc": "2024-02-21T11:01:35",
"channel": "WhatsApp"
}

Flows replies​

When a user completes a WhatsApp Flow, you receive an interactive message of type nfm_reply. The submitted data is in message.custom.interactive.nfm_reply.response_json.

FieldDescription
nfm_reply.nameAlways flow.
response_json.flow_tokenThe flow_token you sent with the original Flows message. Use it to correlate the response.
response_json.*Every other property contains data entered by the user. The property names are those defined in your Flow, so they differ per Flow.
Flows reply
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUUxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "nfm_reply",
"list_reply": null,
"button_reply": null,
"nfm_reply": {
"name": "flow",
"response_json": {
"flow_token": "your-flow-token",
"entered-field-1": "entered-value-1",
"entered-field-2": "entered-value-2"
}
}
},
"meta_received_time": "2024-02-21T11:01:34"
},
"error": ""
},
"groupings": ["", "", ""],
"timeUtc": "2024-02-21T11:01:35",
"channel": "WhatsApp"
}

Call permission replies​

You receive a call permission reply when a user grants, refuses or loses permission for your business to call them. This happens when:

  • The user accepts or rejects a call permission request you sent.
  • The user calls your business, which grants permission automatically.
  • Four consecutive business-initiated calls go unanswered, which revokes permission automatically.

The details are in message.custom.interactive.call_permission_reply.

FieldTypeDescription
responsestringaccept or reject.
is_permanentbooleantrue if the permission does not expire.
expiration_timestampstring | nullFor temporary permissions, the moment the permission expires. null otherwise.
response_sourcestringWhat triggered the update, for example user_action.
Expiry is not notified

No webhook is sent when a temporary permission expires. Use expiration_timestamp to track expiry in your own system.

Accepted (permanent)
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUYxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Received call permission reply.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "call_permission_reply",
"list_reply": null,
"button_reply": null,
"nfm_reply": null,
"payment_method": null,
"call_permission_reply": {
"response": "accept",
"expiration_timestamp": null,
"is_permanent": true,
"response_source": "user_action"
}
},
"meta_received_time": "2026-08-04T12:58:43"
},
"error": ""
},
"groupings": ["", "", ""],
"timeUtc": "2026-08-04T12:58:44",
"channel": "WhatsApp"
}
Accepted (temporary)
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUYxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Received call permission reply.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "call_permission_reply",
"list_reply": null,
"button_reply": null,
"nfm_reply": null,
"payment_method": null,
"call_permission_reply": {
"response": "accept",
"expiration_timestamp": "2026-08-05T12:58:43",
"is_permanent": false,
"response_source": "user_action"
}
},
"meta_received_time": "2026-08-04T12:58:43"
},
"error": ""
},
"groupings": ["", "", ""],
"timeUtc": "2026-08-04T12:58:44",
"channel": "WhatsApp"
}
Rejected
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUYxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Received call permission reply.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"interactive": {
"type": "call_permission_reply",
"list_reply": null,
"button_reply": null,
"nfm_reply": null,
"payment_method": null,
"call_permission_reply": {
"response": "reject",
"expiration_timestamp": null,
"is_permanent": false,
"response_source": "user_action"
}
},
"meta_received_time": "2026-08-04T12:58:43"
},
"error": ""
},
"groupings": ["", "", ""],
"timeUtc": "2026-08-04T12:58:44",
"channel": "WhatsApp"
}

Product orders​

When a user sends you their shopping cart from a product message, you receive an order. You can use it to confirm the order and, for example, send the user a payment link. For how to send product messages, see Product messages.

The order is provided in message.custom.order.

FieldTypeDescription
catalog_idstringID of the catalogue the products belong to.
product_itemsarrayThe products in the cart.
product_items[].product_retailer_idstringYour retailer ID of the product.
product_items[].quantitystringQuantity ordered.
product_items[].item_pricestringUnit price of the product.
product_items[].currencystringISO 4217 currency code of the price.
textstringText the user added to the order, or null.
Numeric values are strings

quantity and item_price are delivered as strings. Convert them before performing calculations, and always validate prices against your own catalogue.

Product order
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUcxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"order": {
"catalog_id": "123456789012345",
"product_items": [
{
"product_retailer_id": "cmcomdevelop-frisbee",
"quantity": "2",
"item_price": "15",
"currency": "EUR"
},
{
"product_retailer_id": "cmcomdevelop-coaster",
"quantity": "6",
"item_price": "7",
"currency": "EUR"
},
{
"product_retailer_id": "cmcomdevelop-mousepad",
"quantity": "1",
"item_price": "9.99",
"currency": "EUR"
}
],
"text": null
},
"meta_received_time": "2021-11-08T12:19:48"
}
},
"groupings": ["", "", ""],
"time": "2021-11-08 13:19:49",
"timeUtc": "2021-11-08T12:19:49",
"channel": "WhatsApp"
}

Notifications​

Deleted messages​

When a user deletes a message they sent you, you receive a notification. message.custom.deletedMessage contains the reference of the deleted message, as received in an earlier webhook.

️ Remove deleted content

When you receive this notification, remove the referenced message from your systems.

Deleted message
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUgxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"deletedMessage": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"meta_received_time": "2021-11-08T12:19:48"
}
},
"groupings": ["", "", ""],
"time": "2021-11-08 13:19:49",
"timeUtc": "2021-11-08T12:19:49",
"channel": "WhatsApp"
}

Error notifications​

When Meta cannot (fully) deliver a message from a user, you still receive a notification so you know the user tried to contact you. The reason is provided by Meta in message.error, for example Message type is not currently supported.

Consider responding to the user, for example by asking them to send their message in a different format.

Error notification
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUkxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"meta_received_time": "2022-11-08T12:19:48"
},
"error": "Message type is not currently supported"
},
"groupings": ["", "", ""],
"time": "2022-11-08 13:19:49",
"timeUtc": "2022-11-08T12:19:49",
"channel": "WhatsApp"
}

Welcome requests​

When this feature is activated, you receive a notification the first time a user opens a chat with your business, before they have sent a message. Use it to greet the user with a personalised welcome message, which is particularly useful for customer service and account management.

The notification is sent only if no message thread exists yet between the user and your business number. It is identified by message.custom.message_type with the value request_welcome.

Welcome request
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUoxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "User request welcome message",
"custom": {
"meta_received_time": "2022-11-08T12:19:48",
"message_type": "request_welcome"
}
},
"groupings": ["", "", ""],
"time": "2022-11-08 13:19:49",
"timeUtc": "2022-11-08T12:19:49",
"channel": "WhatsApp"
}

Marketing preference updates​

You receive a notification when a user changes their preference for receiving marketing messages from your business:

  • The user stops marketing messages (opt-out).
  • The user resumes marketing messages (opt-in).

The change is described in message.text.

Respect opt-outs

When a user opts out, update your contact records and stop sending them marketing templates until they opt back in.

Resumed marketing messages
{
"reference": "48b65fde-f73a-4c77-b600-a581807931ed",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "User requested to resume marketing messages",
"custom": {
"meta_received_time": "2025-12-05T11:00:34"
},
"error": ""
},
"time": "2025-12-05 12:00:35",
"timeUtc": "2025-12-05T11:00:35",
"channel": "WhatsApp"
}

Ad referrals (Click-to-WhatsApp)​

When a user starts a conversation by clicking an ad or post with a Click-to-WhatsApp, Click-to-Facebook or Click-to-Instagram call to action, the first inbound message contains a message.referral object. It tells you which ad or post the user came from.

Use the click ID (ctwa_clid) to send conversion events back to Meta through the Meta Conversions API. Meta Ads Manager uses these events to measure and optimise your campaigns, for example to retarget users who did not convert.

Availability

The Meta Conversions API for WhatsApp is only available to businesses based outside the United Kingdom, the European Union and Japan.

FieldTypeDescription
source_urlstringMeta URL of the ad or post.
source_idstringMeta ID of the ad or post.
source_typestringad or post.
headlinestringHeadline of the ad or post.
bodystringBody text of the ad or post.
media_typestringType of media in the ad or post, if any: image or video.
image_urlstringURL of the image, if the ad or post contains one.
ctwa_clidstringClick ID assigned by Meta. Required when sending conversion events to Meta.
Ad referral
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUsxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe"
},
"to": {
"number": "0031850123456"
},
"message": {
"text": "Hi, I'd like to know more about your offer.",
"custom": {
"meta_received_time": "2025-06-30T10:23:34"
},
"referral": {
"source_url": "https://fb.me/xxxxxxxxx",
"source_id": "120200000000000000",
"source_type": "ad",
"headline": "Summer sale",
"body": "Chat with us on WhatsApp for 20% off.",
"media_type": "image",
"image_url": "https://scontent.xx.fbcdn.net/xxxxxxxx.jpg",
"ctwa_clid": "AfezXXXXlzjkdgEtWs6Coke3jFaNpq7eUgd4H76BmKbOZFw31hIHf-7JEPkRjs_kUVIF0CMzfBkVux_XXX2ZzVPPja_GuHXXXXi9Nt0l3r5d4BZPwNQJpAiQNJ2E32nOcVDA"
}
},
"groupings": ["", "", ""],
"time": "2025-06-30 12:23:34",
"timeUtc": "2025-06-30T10:23:34",
"channel": "WhatsApp"
}