WhatsApp channel message support
The WhatsApp channel of the Conversation API supports a wide variety of message types, including the the rich template, media, and location message types supported by the WhatsApp API.
Sending Messages
Prior to sending messages on the WhatsApp channel using the Conversation API generic message format, note the following:
- Sending a generic message format requires a started customer care session . Sending messages outside of a customer care session requires a template .
- All business initiated conversations on the WhatsApp channel should start with an “Opt-In” by the user. This can be collected through any third party channel. For example in an SMS message, a web form, email etc. Businesses must also provide a method by which customers may opt-out of receiving future messages from your organization.
Note:
Starting June 30th, 2022, the Conversation API will not check whether recipients have opted in before sending messages. It is the user's responsibility to ensure that the recipient has opted in before sending.
The following table details the mapping between the Conversation API generic message format and how WhatsApp renders the messages on mobile devices:
Message Type | Natively Supported? | Special Instructions |
---|---|---|
Text Message | Yes, this type of message is natively supported. For example: |
The code to send a text message for this channel doesn't differ from the generic message and can be viewed here. |
Media Message | Yes, this type of message is natively supported for the following media types (the WhatsApp channel will automatically detect what type of WhatsApp media message to use):
|
The code to send a media message for this channel doesn't differ from the generic message and can be viewed here. |
Choice Message | This type of message is natively supported (through the use of quick reply buttons) if:
If these conditions are not met, the message is converted into plain text. |
The code to send a choice message for this channel doesn't differ from the generic message and can be viewed here. |
Card Message | This type of message is natively supported if you only include text choices in your card message. Note that:
|
The code to send a card message for this channel doesn't differ from the generic message and can be viewed here. |
Carousel Message | No, this type of message will be converted into plaintext. For example: |
The code to send a carousel message for this channel doesn't differ from the generic message and can be viewed here. |
Location Message | Yes, this type of message is natively supported. For example: |
The code to send a location message for this channel doesn't differ from the generic message and can be viewed here. |
Choice List Message | Yes, this type of message is natively supported. For example: The detailed view of the message is displayed below: |
The code to send a list message for this channel doesn't differ from the generic message and can be viewed here. |
Product List Message (Single Product) | Yes, this type of message is natively supported. For example: The detailed view of the message is displayed below: |
The code to send a list message for this channel doesn't differ from the generic message and can be viewed here. |
Product List Message (Multi-Product) | Yes, this type of message is natively supported. For example: The detailed view of the message is displayed below: |
The code to send a list message for this channel doesn't differ from the generic message and can be viewed here. |
Explicit Channel Messages
Conversation API provides a way to use channel specific message formats. If you know the underlying channel's API (in this case, the WhatsApp Business API), and you want to use a feature that's not supported by Conversation API message types, you can pass the JSON format of the WhatsApp Business API to Conversation API too. When you want to use a channel specific format, you need to pass this JSON as an escaped string to Conversation API.
For example, consider the Interactive List message. While we can send this message as a choice list message, it can also be sent using the WhatsApp Business API. This example message is sent using a Conversation API POST
to the messages:send
endpoint:
{
"message": {
"explicit_channel_message": {
"WHATSAPP": "{\r\n \"to\": \"{{to}}\",\r\n \"type\": \"interactive\",\r\n \"recipient_type\": \"INDIVIDUAL\",\r\n \"interactive\": {\r\n \"type\": \"list\",\r\n \"body\": {\r\n \"text\": \"This is the card title\"\r\n },\r\n \"footer\": {\r\n \"text\": \"This is the card description\"\r\n },\r\n \"action\": {\r\n \"button\": \"Menu\",\r\n \"sections\": [\r\n {\r\n \"rows\": [\r\n {\r\n \"id\": \"firstreply\",\r\n \"title\": \"First Reply\"\r\n },\r\n {\r\n \"id\": \"secondreply\",\r\n \"title\": \"Second Reply\"\r\n },\r\n {\r\n \"id\": \"thirdreply\",\r\n \"title\": \"Third Reply\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n }\r\n}"
}
}
}
The rendered message:
Receiving Delivery Receipts
Messages sent on WhatsApp channel can have three statuses: DELIVERED
, READ
, or FAILED
.
If the status is FAILED
, a reason will be included that provides more information about the failure.
Note:
Not all messages that are successfully delivered have both DELIVERED
and READ
statuses. Only a READ
receipt is sent if the contact's WhatsApp app and conversation are active when the message is received.
Below is an example of a Conversation API POST
to the MESSAGE_DELIVERY
webhook with a READ
receipt; a FAILED
or DELIVERED
receipt would have a different status
, and a FAILED
status would have a reason
.
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"accepted_time": "2020-06-22T11:05:53.910Z",
"message_delivery_report": {
"message_id": "01EBDV9EFP66ZA0GQJ9MCX1V9H",
"conversation_id": "01EB199XQ2CBY50K6WZD9S1A22",
"status": "READ",
"channel_identity": {
"channel": "WHATSAPP",
"identity": "+46702471483",
"app_id": ""
},
"contact_id": "01EB197NDA4W7V15NPRCVV0S79",
"metadata": "",
"processing_mode": "CONVERSATION"
},
"message_metadata": "{\"pricing_category\":\"user_initiated\",\"whatsapp_conversation_id\":\"a49709b572981c281648d7d23e95412c\"}"
}
Receiving Pricing Model Information
Starting February 1st, 2022, the WhatsApp pricing model is conversation-based instead of notification-based. This means that customers are charged per conversation. A conversation starts with the first delivered message and includes all messages delivered in a 24-hour session. The price for the conversation depends on the pricing category of the conversation:
- User-initiated , which defines conversations initiated in response to a user message.
- Business-initiated , which defines conversations initiated from a business outside the 24-hour customer service window. Note that starting a conversation outside the 24-hour customer service window requires a template message.
- Referral conversion , which defines conversations that do not incur a charge. These conversations are typically initiated when an end-user messages the business by clicking a call-to-action button on an ad. For example, a user clicking on a Facebook ad may trigger a referral conversion conversation.
Note
For more information regarding this WhatsApp update, see their article on Conversation-Based Pricing.
To inform the Conversation API user about the pricing of their WhatsApp conversation, delivery receipt callbacks with the DELIVERED
status will contain additional message_metadata
with info about:
-
pricing_category
, which is the pricing category for the conversation. -
whatsapp_conversation_id
, which is the WhatsApp conversation id (messages with the same id belong to the same conversation).
For example:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"accepted_time": "2020-06-22T11:05:53.910Z",
"message_delivery_report": {
"message_id": "01EBDV9EFP66ZA0GQJ9MCX1V9H",
"conversation_id": "01EB199XQ2CBY50K6WZD9S1A22",
"status": "READ",
"channel_identity": {
"channel": "WHATSAPP",
"identity": "+46702471483",
"app_id": ""
},
"contact_id": "01EB197NDA4W7V15NPRCVV0S79",
"metadata": "",
"processing_mode": "CONVERSATION"
},
"message_metadata": "{\"pricing_category\":\"user_initiated\",\"whatsapp_conversation_id\":\"a36709b572981c281648d7d23d91588z\"}"
}
When the first delivery receipt with a DELIVERED
status and a new whatsapp_conversation_id
is received, the customer is charged for a new conversation. All messages sent to the same recipient within a 24-hour window are part of that same conversation, and don't incur additional charges.
Receiving Messages
WhatsApp channel supports various kinds of contact messages - text, media, media card, location, and choice response.
Note:
Please note that the media URLs included in the contact messages are valid for 7 days. After that the media is deleted from Conversation API storage.
All of these are delivered by Conversation API with a POST
to the MESSAGE_INBOUND
webhook:
Text message response webhook example
Below is an example of a Conversation API POST
to the MESSAGE_INBOUND
webhook for a text message response:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"accepted_time": "2020-06-22T10:55:39.534687Z",
"message": {
"id": "01EBDTPPG3Q3EH14H7DY8X09MG",
"direction": "TO_APP",
"contact_message": {
"text_message": {
"text": "Hi from contact"
}
},
"channel_identity": {
"channel": "WHATSAPP",
"identity": "46712312312",
"app_id": ""
},
"conversation_id": "01EB199XQ2CBY50K6WZD9S1A22",
"contact_id": "01EB197NDA4W7V15NPRCVV0S79",
"metadata": "",
"accept_time": "2020-06-22T10:55:39.521500Z"
}
}
Media message response webhook example
Below is an example of a Conversation API POST
to the MESSAGE_INBOUND
webhook for a media message response:
{
"app_id": "01EB37HMH1M6SV18ASNS3G135H",
"accepted_time": "2020-10-01T12:10:55.073703Z",
"event_time": "2020-10-01T12:10:53.991Z",
"project_id": "c36f3d3d-1513-4edd-ae42-11995557ff61",
"message": {
"id": "01EKJ1534NWK5R02TGWEJN13HA",
"direction": "TO_APP",
"contact_message": {
"media_message": {
"url": "https://1vxc0v12qhrm1e72gq1mmxkf-wpengine.netdna-ssl.com/wp-content/uploads/2019/05/Sinch-logo-Events.png"
}
},
"channel_identity": {
"channel": "WHATSAPP",
"identity": "46712312312",
"app_id": ""
},
"conversation_id": "01EKJ0KSWXMVDF05MG9TQ20S06",
"contact_id": "01EKA07N79THJ20WSN6AS30TMW",
"metadata": "",
"accept_time": "2020-10-01T12:10:55.060170Z"
}
}
Media card message response webhook example
Below is an example of a Conversation API POST
to the MESSAGE_INBOUND
webhook for a media card message response:
{
"app_id": "01EB37HMH1M6SV18ASNS3G135H",
"accepted_time": "2020-10-01T12:10:55.073703Z",
"event_time": "2020-10-01T12:10:53.991Z",
"project_id": "c36f3d3d-1513-4edd-ae42-11995557ff61",
"message": {
"id": "01EKJ1534NWK5R02TGWEJN13HA",
"direction": "TO_APP",
"contact_message": {
"media_card_message": {
"url": "https://1vxc0v12qhrm1e72gq1mmxkf-wpengine.netdna-ssl.com/wp-content/uploads/2019/05/Sinch-logo-Events.png",
"caption": "caption text"
}
},
"channel_identity": {
"channel": "WHATSAPP",
"identity": "46712312312",
"app_id": ""
},
"conversation_id": "01EKJ0KSWXMVDF05MG9TQ20S06",
"contact_id": "01EKA07N79THJ20WSN6AS30TMW",
"metadata": "",
"accept_time": "2020-10-01T12:10:55.060170Z"
}
}
Location message response webhook example
Below is an example of a Conversation API POST
to the MESSAGE_INBOUND
webhook for a location message response:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"accepted_time": "2020-06-22T10:57:36.074692Z",
"message": {
"id": "01EBDTT89ZGTGM0P70W0RK0YR2",
"direction": "TO_APP",
"contact_message": {
"location_message": {
"title": "ICA Jägaren",
"coordinates": {
"latitude": 55.727802,
"longitude": 13.175061
},
"label": ""
}
},
"channel_identity": {
"channel": "WHATSAPP",
"identity": "46712312312",
"app_id": ""
},
"conversation_id": "01EB199XQ2CBY50K6WZD9S1A22",
"contact_id": "01EB197NDA4W7V15NPRCVV0S79",
"metadata": "",
"accept_time": "2020-06-22T10:57:36.060961Z"
}
}
Choice message response webhook example
Below is an example of a Conversation API POST
to the MESSAGE_INBOUND
webhook for a choice message response:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"accepted_time": "2020-06-22T11:00:32.866988Z",
"message": {
"id": "01EBDTZMYPHM0G1D0AJFEZ0A4P",
"direction": "TO_APP",
"contact_message": {
"choice_response_message": {
"message_id": "01EBDTZ9SN8HTW092K56PH1GDS",
"postback_data": "email_postback"
}
},
"channel_identity": {
"channel": "WHATSAPP",
"identity": "46712312312",
"app_id": ""
},
"conversation_id": "01EB199XQ2CBY50K6WZD9S1A22",
"contact_id": "01EB197NDA4W7V15NPRCVV0S79",
"metadata": "",
"accept_time": "2020-06-22T11:00:32.852315Z"
}
}
Receiving WABA events
In addition to messages, the WhatsApp channel allows you to receive event information about Quality Rating or Daily Limit changes.
All of these are delivered by Conversation API with a POST
to the CHANNEL_EVENT
webhook:
Quality Rating changed webhook example
Below is an example of a Conversation API POST
to the CHANNEL_EVENT
webhook for a Quality Rating change event:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"event_time": "2022-07-25T06:23:46Z",
"project_id": "c36f3d3d-1513-4edd-ae42-11995557ff61",
"channel_event_notification": {
"channel_event": {
"channel": "WHATSAPP",
"event_type": "WHATS_APP_QUALITY_RATING_CHANGED",
"additional_data": {
"quality_rating": "GREEN"
}
}
},
"message_metadata": ""
}
Daily Limit changed webhook example
Below is an example of a Conversation API POST
to the CHANNEL_EVENT
webhook for a Daily Limit change event:
{
"app_id": "01E8RCZPK7HFV70FFDWFFK0EXK",
"event_time": "2022-07-26T08:15:00Z",
"project_id": "c36f3d3d-1513-4edd-ae42-11995557ff61",
"channel_event_notification": {
"channel_event": {
"channel": "WHATSAPP",
"event_type": "WHATS_APP_DAILY_LIMIT_CHANGED",
"additional_data": {
"daily_limit": "TIER_100K"
}
}
},
"message_metadata": ""
}