Setup
Enabling the channel
Please follow the guidance here to setup the WhatsApp channel in Dotdigital prior to attempting to send via the API.
Register template(s)
To initiate a conversation in WhatsApp you may only send a registered and approved templated message, so you should follow this guidance on how to setup a template to ensure you can send your first WhatsApp message via API.
Channel Identifier
In the Omnichannel API this channel can be referenced using: whatsApp
This identifier can be used in the rules array, channelOptions and customBody sections.
Sending an WhatsApp message
Sending an WhatsApp message via the Omnichannel API is simple. You are required to ensure that your channel rules include the whatsApp channel and you specify either a phoneNumber in international format or a profileId with a phone number in the to section of your request. The message itself can be of two different types which are described below:
Message Types
The message type you can send is governed by whether you are in a conversation with a WhatsApp user or not. A conversation on WhatsApp is considered to be occurring for 24 hours after the last inbound message you received from a WhatsApp user.
You may send only template messages outside of a conversation window and either template or session messages within a conversation window. See below for details of each type of message:
Template Messages
If you are not in a conversation with a WhatsApp user then you may only send a pre-approved template based message. You can create and manage your WhatsApp message templates in the WhatsApp manager on Meta and more help on how to do this can be found in this article here .
You will need to note the template id's and the template namespace to use them with the API.
Templates may be defined in multiple languages. Templates can also contain parameters to allow personalization and specifics to be included in the message.
Sending a template message
To use the Omnichannel API to send a template message you will need to include a special message part which is used to identify the template required and pass the parameters required for the template. For more information on using message parts with the Omnichannel API please see Multi part messages.
The MIME type for the message part is whatsapp/template and as only the WhatsApp channel can use this MIME type please include a channel filter using the channels array and include the value whatsApp. The following additional fields are required in the data field of the message part:
Field | Description | Example value | Required |
---|---|---|---|
namespace | The namespace for your template, this in combinaiton with your template name makes it unique throughout WhatsApp. You can find this value in the templates section for your WhatsApp channel. | de0464f9_3d87_cb42_b0d7_d7651ab3337a | Yes |
templateName | The unique name of the template you want to send. You can find this value in the templates section for your WhatsApp channel. | dispatch_confirmation | Yes |
languageCode | The desired language you want the template sent in. You must have pre-registered the language variant of the template prior to using it. Contact your Client Engagement Manager to do this. | en | Yes |
parameters | This is the array of parameters to be merged into your template. Ensure the order of the values in the array matches the order you want them merged into the template. The parameters can be of the following types: default – A string value currency – A currency value that will be localized automatically - date_time – A date time that will be localized automatically Each value passed should be a object with a default field and the plain text version of the value required. e.g.{ "default": "A text field" }If you want to use one of the localizable types then you need to pass additional details along with the default value, such as currency code etc... Please see the section below for more details on Localizable Parameters.Include values for all the parameters in the template, ensuring the types match those you registered! | [ { "default": "Dave" }, { "default": "1234" } ] | No |
Variable ordering is important!
When passing parameters with your template message sends it is critical to order the parameters match those used in your template.
Localizable Parameters
When sending a template with parameters you may want to send values that need adapting depending on the recipients locality, such as currency values or dates. WhatsApp supports localization of currency and date time parameters, but you must pass additional details for these localizable parameters.
All parameters objects must contain a default value, which is used should any issues be encountered trying to localize the parameter and this should be a generic plain text representation of the value.
Currency Values
In order to send a localizable currency value you need to includes the following fields in your parameter object:
Field | Description | Example value | Required |
---|---|---|---|
default | generic plain text representation of the currency value which is used should localization not be possible | 199 USD | Yes |
currency | A currency object to describe the currency value and source currency | "currency": { "currency_code": "USD", "amount_1000": 100990 } | Yes |
currency object
Field | Description | Example value | Required |
---|---|---|---|
currency_code | The ISO currency code your charge is based on. | USD | Yes |
amount_1000 | The amount to charge in one thousandths of the currency. e.g. $9.99 is 9990 , worked out by 9.99 * 1000 | 9990 | Yes |
Date Time Values
In order to send a localizable date time value you need to includes the following fields in your parameter object:
Field | Description | Example value | Required |
---|---|---|---|
default | generic plain text representation of the date time value which is used should localization not be possible | 1st January 2019, 14:45 | Yes |
date_time | A date_time object to describe the date and time using individual component parts | "date_time": { "component": { "day_of_week": 5, "day_of_month": 25, "year": 1977, "month": 2, "hour": 15, "minute": 33 } | Yes |
date_time object
Field | Description | Example value | Required |
---|---|---|---|
component | A component object to describe the date and time using individual component parts | "component": { "day_of_week": 5, "day_of_month": 25, "year": 1977, "month": 2, "hour": 15, "minute": 33 } | No |
component object
Field | Description | Example value | Required |
---|---|---|---|
day_of_week | The day of the week as an integer with 1 = Monday and 7 = Sunday | 5 | No |
day_of_the_month | The day of the month as an integer | 25 | No |
year | The year as a 4 digit integer | 1977 | No |
month | The month as an integer | 2 | No |
hour | The hour as an integer based on the 24 hour clock | 15 | No |
minute | The minute as an integer | 33 | No |
calendar | The type of calendar you want to use, defaults to Gregorian. Choose from GREGORIAN or SOLAR_HIJRI | GREGORIAN | No |
Example Template Sends
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"channels": [
"whatsApp"
],
"type": "whatsapp/template",
"data": {
"namespace": "de0464f9_3d87_cb42_b0d7_d7651ab3337a",
"templateName": "dispatch_confirmation",
"languageCode": "en",
"parameters": [
{
"default": "Dave"
},
{
"default": "1234"
}
]
}
}
]
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"channels": [
"whatsApp"
],
"type": "whatsapp/template",
"data": {
"namespace": "ce0464f9_3d87_fb42_b0d7_d7651ab3337a",
"templateName": "dispatch_confirmation",
"languageCode": "en",
"parameters": [
{
"default": "February 25, 1977",
"date_time": {
"component": {
"day_of_week": 5,
"day_of_month": 25,
"month": 2,
"year": 1977
}
}
}
]
}
}
],
"metadata": {
"data": "My correlation data"
}
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"channels": [
"whatsApp"
],
"type": "whatsapp/template",
"data": {
"namespace": "de0464f9_3d87_cb42_b0d7_d7651ab3337a",
"templateName": "dispatch_confirmation",
"languageCode": "en",
"parameters": [
{
"default": "$9.99",
"currency": {
"currency_code": "USD",
"amount_1000": 9990
}
}
]
}
}
],
"metadata": {
"data": "My correlation data"
}
}
Sending Media Templates
If you have chosen to use media in your WhatsApp templates then to pass the additional information you will need to use the custom body option.
The JSON you need to pass in the custom body to use a media template is described in the WhatsApp docs here
Note: We automatically populate the "to" field within the custom body block, so no need to specify it.
The following example is of a call to send a media template with an image header and two parameters in the body:
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"customBody": {
"whatsApp": {
"type": "template",
"template": {
"namespace": "ce0464f9_3d87_fb42_b0d7_d7651ab3337a",
"name": "appointment_booked",
"language": {
"policy": "deterministic",
"code": "en"
},
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"link": "https://files.readme.io/6102a7e-dotdigital_logo_stacked_reversed_RGB.png"
}
}
]
},
{
"type": "body",
"parameters": [
{
"type": "date_time",
"date_time": {
"fallback_value": "2021-09-02",
"day_of_week": 4,
"day_of_month": 2,
"year": 2021,
"month": 9,
"hour": 12,
"minute": 00
}
},
{
"type": "text",
"text": "London"
}
]
}
]
}
}
}
}
Session Messages
Session messages can be sent within a WhatsApp conversation session, which lasts 24 hours from the last inbound you received from a WhatsApp user. Session messages are designed to be used to allow businesses to send the information necessary to answer a WhatsApp users queries and therefore are free format.
To use the Omnichannel API to send a session messages you can use either the standard body field to send text based messages or for multimedia use muli-part messages. For more information on using message parts with the Omnichannel API please see Multi part messages.
The following message types are supported by WhatsApp:
- Text (with optional URL preview)
- Image (JPG, JPEG, PNG) with optional text comment
- Audio (AAC, M4A, AMR, MP3, OGG, OPUS)
- Documents (PDF, DOC(X), PPT(X), XLS(X))
Text Formatting
WhatsApp supports simple text formatting in text based messages that can be used to help communicate your message more effectively. The following formatting annotations are supported:
Format | Annotation | Example |
---|---|---|
Bold | * (Asterisk) | Your order has shipped priority |
Italics | _ (Underscore) | This is an estimated delivery date |
~Strike through~ | ~ (Tilde) | ~Shipping charge £10.00~ |
Code | ``` (3 x Back quotes) | console.log("test"); |
Example Session Message Sends
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"body": "A text session message via WhatsApp"
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"body": "A _formatted_ text session message via *WhatsApp*"
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"body": "Check out this video on YouTube: https://www.youtube.com/watch?v=oJLcwqgVOKM",
"channelOptions": {
"whatsApp": {
"enableUrlPreview": true
}
}
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"type": "image/png",
"url": "https://files.readme.io/6102a7e-dotdigital_logo_stacked_reversed_RGB.png"
}
]
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"type": "image/png",
"url": "https://files.readme.io/6102a7e-dotdigital_logo_stacked_reversed_RGB.png"
},
{
"type": "text/plain",
"data": "My image caption"
}
]
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"type": "audio/mp3",
"url": "https://sample-videos.com/audio/mp3/crowd-cheering.mp3"
}
]
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"messageParts": [
{
"type": "application/pdf",
"url": "http://cdn.dnky.co/docs/example.pdf",
"name": "Overview.pdf"
}
]
}
Message Length
The maximum length of a text based WhatsApp message supported is 4096 characters.
Channel Options
The following additional channel options can be used to control the WhatsApp channels most common options. To use the channel options create a object with your options in the requests channelOptions section in the whatsApp property:
Property | Type | Description |
---|---|---|
phoneNumber | string | The registered WhatsApp phone number to send the message from. Default from channel configuration will be used if not specified. |
enableUrlPreview | Boolean | If set to true any URL's sent in a text session message will have a URL preview rendered underneath. |
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"body": "A text session message via WhatsApp",
"channelOptions": {
"whatsApp": {
"phoneNumber": "447860041651"
}
}
}
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"body": "Check out this video on YouTube: https://www.youtube.com/watch?v=oJLcwqgVOKM",
"channelOptions": {
"whatsApp": {
"enableUrlPreview": true
}
}
}
Custom Body
The Omnichannel API automatically creates WhatsApp messages for you if you only define the body property or multi parts when sending a message, but you can override this if you use the customBody property and define a whatsApp object within it This can be useful for accessing features in the channel we don't support in our common message format.
Details of how to create a WhatsApp business message can be found here.
Examples of sends using WhatsApp custom bodies are:
{
"to": {
"phoneNumber": "447123123123"
},
"rules": [
"whatsApp"
],
"customBody": {
"whatsApp": {
"preview_url": true,
"text": {
"body": "You have to check out this amazing messaging service https://www.whatsapp.com/"
}
}
}
}
Ensure you specify a "to" block still!
When using the customBody option with the SMS channel you still need to specify the phoneNumber in the to block as this will be used for profile identification.
Receipts and Inbounds
To receive feedback or inbound messages from WhatsApp sends please see the following:
Inbound Messages
Allows you to receive messages sent from WhatsApp users to your hosted WhatsApp phone numbers. Messages are delivered to a URL of your choosing using the webhook system. See the Inbound event in the Message Events section for more details.
Receipts
If you need to to know the status of messages you've sent using one of our APIs, you can request that delivery receipts are forwarded to a URL of your choosing using the webhook system. See the events in the Message Events section for more details on the receipt events you can receive.
You can receive the following types of receipts:
- Sent
- Delivered
- Read
- Expired
- Failed
Specific Channel Data
The WhatsApp channel carries the following extra channel specific data in the message.sent webhook event which may be of use in your integrations. The channel data can be found in the message.sent webhook events in the payload -> channelData node as illustrated below:
"channelData": {
"whatsApp": {
"virtualDeviceNumber": "447123123123",
"originatorPhoneNumber": "447123123123",
"isTemplateMessage": true,
"isWithinConversationWindow": false,
"phoneNumberCountryCode": "GB"
}
}
{
"eventId": "f10fd498-1f96-4f3b-a0f8-289e34928e15",
"accountId": 12345,
"apiSpaceId": "62d1780d-8440-480a-b268-20b1eb50a4ff",
"name": "message.sent",
"payload": {
"id": "c94a82da-55e8-4a29-922c-ba4aed3e5990",
"details": {
"channel": "whatsApp",
"channelStatus": {
"whatsApp": {
"status": "sent",
"updatedOn": "2024-10-29T10:08:59.000Z",
"details": {
"contacts": [
{
"input": "447001001001",
"wa_id": "447001001001"
}
],
"messages": [
{
"id": "gBEGTHcVF4YFAgkbt37BX1L-tvg"
}
],
"meta": {
"api_status": "stable",
"version": "2.55.1"
},
"conversation": {
"expiration_timestamp": 1730282580,
"id": "f9265945b17526717f739e445ed056f2",
"origin": {
"type": "utility"
}
},
"id": "gBEGTHcVF4YFAgkbt37BX1L-tvg",
"message": {
"recipient_id": "447001001001"
},
"pricing": {
"billable": true,
"category": "utility",
"pricing_model": "CBP"
},
"status": "sent",
"timestamp": "1730196539",
"type": "message"
}
},
"fbMessenger": {
"status": "pending"
},
"email": {
"status": "pending"
}
}
},
"channelData": {
"whatsApp": {
"virtualDeviceNumber": "447123123123",
"originatorPhoneNumber": "447123123123",
"isTemplateMessage": true,
"isWithinConversationWindow": false,
"phoneNumberCountryCode": "GB"
}
},
"updatedOn": "2024-10-29T10:08:59.000Z",
"_apiSpaceId": "62d1780d-8440-480a-b268-20b1eb50a4ff"
},
"revision": 3,
"etag": "\"2e-EgwZ9mai3uos3CKWlv4t8Dim1gw\"",
"timestamp": "2024-10-29T10:09:00.072Z"
}
The data is as follows:
Path | Field | Description |
---|---|---|
virtualDeviceNumber | The WhatsApp phone number assigned to the virtual device that sent the message. | |
originatorPhoneNumber | The originating phone number used to send the message. | |
isTemplateMessage | Boolean indicating whether the message sent was a template based message or not | |
isWithinConversationWindow | Boolean indicating whether the message was sent within a conversation window or not. | |
phoneNumberCountryCode | The two character country code for the phone number you sent to. |