Skip to main content

Messages

https://whatsapp.turn.io/v1/messages

This endpoint responsible for sending messages via WhatsApp. Messages for WhatsApp are classified as:

Turn's outbound messaging API is synchronous to the upstream gateways. If Turn returns with a success response, the upstream gateway has accepted the message for delivery. Turn does not queue outbound messaging.

note

This endpoint is rate limited on a per number basis. See rate limiting for more information.

Text Messages

$ curl -X POST "https://whatsapp.turn.io/v1/messages" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '
{
"preview_url": false | true,
"recipient_type": "individual",
"to": "whatsapp-id",
"type": "text",
"text": {
"body": "your-text-message-content"
}
}'


> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

Make sure to replace token with your access token.

A successful response includes a messages object with an identifier for the newly created message.

An unsuccessful response will contain an error message. See Error and Status Codes for more information.

Parameters

ParameterRequiredDefaultDescription
preview_urlnofalseSpecifying preview_url in the request is optional when not including a URL in your message. To include a URL preview, set preview_url to true in the message body and make sure the URL begins with http:// or https://.
toyesWhen recipient_type is individual, this field is the WhatsApp ID (phone number) returned from contacts endpoint.
typenotextSpecifying type in the request is optional when you are sending a text message.
text.bodyyesThe text to send

Media Messages

Use the messages endpoint to send messages containing audio, images, documents, or stickers to your customers.

When you send a message that includes media, you must provide the ID of the uploaded media in the request body. You must also specify the type of media that you are sending: audio, image, video, document, or sticker. When the request is received, the media is uploaded to the WhatsApp server and sent to the user indicated in the to field.

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"recipient_type": "individual",
"to": "whatsapp-id",
"type": "audio" | "document" | "image" | "sticker" | "video",

"audio": {
"id": "your-media-id",
}

"document": {
"id": "your-media-id",
"caption": "your-document-caption"
}

"image": {
"id": "your-media-id",
"caption": "your-image-caption"
}

"sticker": {
"id": "your-media-id"
}

"video": {
"id": "your-media-id",
"caption": "your-video-caption"
}
}
'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

The successful response includes a messages object with a message ID. An unsuccessful response will contain an error message. See Error and Status Codes for more information on errors.

Parameters

| Name | Required | Default | Description | | ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | | to | yes | | This field is the WhatsApp ID (phone number) returned from contacts endpoint. | | type | yes | no | text | Options: text, image, audio, document, hsm, sticker | | <media-type>.id | | | The media object ID, which is returned when the media is successfully uploaded to the WhatsApp Business API Client with the media endpoint. | | <media-type>.caption | | | Describes the specified image or document media. Do not use with audio or sticker media. |

Additional documentation:

Templated Messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "template",
"template": {
"namespace": "template-namespace",
"name": "template-name",
"language": {
"code": "en",
"policy": "deterministic"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "text",
"text": "header placeholder value"
}
]
},
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "body placeholder 1 value"
},
{
"type": "text",
"text": "body placeholder 2 value"
}
]
}
]
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

As with normal messages, the message is sent to the /v1/messages endpoint. What's different about sending templated messages is that the message type is set to template and a template object is provided with information such as which message template to use.

The template property indicates the namespace and the name of the message template that should be sent. It also includes a list of components that will be used to build the template header, footer, body and buttons.

The namespace can be determined using the Turn web application as follows:

  • Navigate to Settings > API & Webhooks.
  • Click the Generate Credentials button.
  • View your Message Template API details including namespace and access token.

Please refer to the official WhatsApp documentation for more details.

note

Please note that every new number is limited to sending message templates to a maximum of 1000 users a day. As a numbers' total audience grows WhatsApp will extend the per day limit as per the tiers outlined in the Quality Rating and Messaging Limits documentation. WhatsApp will not start a number on a higher tier and Turn is not able to manually change or request a tier change for a number. Tiers are determined by WhatsApp based on a numbers' organic growth and overall quality rating.

Interactive Messages

Sending quick reply messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "interactive",
"interactive": {
"type": "button",
"header": { # optional
"type": "text" | "image" | "video" | "document",
"text": "your text"
# OR
"document": {
"id": "your-media-id",
"filename": "some-file-name"
}
# OR
"document": {
"link": "the-provider-name/protocol://the-url",
"provider": {
"name": "provider-name",
},
"filename": "some-file-name"
},
# OR
"video": {
"id": "your-media-id"
}
# OR
"video": {
"link": "the-provider-name/protocol://the-url",
"provider": {
"name": "provider-name"
}
}
# OR
"image": {
"id": "your-media-id"
}
# OR
"image": {
"link": "http(s)://the-url",
"provider": {
"name": "provider-name"
}
}
}, # end header
"body": {
"text": "your-text-body-content"
},
"footer": { # optional
"text": "your-text-footer-content"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "unique-postback-id",
"title": "First Button’s Title"
}
},
{
"type": "reply",
"reply": {
"id": "unique-postback-id",
"title": "Second Button’s Title"
}
}
]
}
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

Sending list messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "interactive",
"interactive": {
"type": "list",
"header": {
"type": "text",
"text": "your-header-content"
},
"body": {
"text": "your-text-message-content"
},
"footer": {
"text": "your-footer-content"
},
"action": {
"button": "cta-button-content",
"sections": [
{
"title":"your-section-title-content",
"rows": [
{
"id":"unique-row-identifier",
"title": "row-title-content",
"description": "row-description-content",
}
]
},
{
"title":"your-section-title-content",
"rows": [
{
"id":"unique-row-identifier",
"title": "row-title-content",
"description": "row-description-content",
}
]
}
]
}
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

Sending location request messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "interactive",
"interactive": {
"type": "location_request_message",
"body": {
"type": "text",
"text": "Please let us know where you are?"
},
"action": {
"name": "send_location"
}
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrX"
}]
}

As with normal messages, the message is sent to the /v1/messages endpoint. What's different about sending interactive messages is that the message type is set to interactive and an interactive object is provided with information, such as which type of interactive message one wants to use along with its payload. Currently, button and list types are supported.

The interactive property is different depending on the type of interactive message that should be sent (buttons or list message). It includes an action property that will be used to build the set of options for the message.

Please refer to the official WhatsApp documentation for more details.

Interactive Templated Messages

Sending an interactive message simply boils down to sending a templated message using a template that contains buttons.

Please refer to the official WhatsApp documentation for more details.

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "template",
"template": {
"namespace": "template-namespace",
"name": "template-name",
"language": {
"code": "en",
"policy": "deterministic"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "body placeholder 1 value"
}
]
},
{
"type": "button",
"sub_type" : "quick_reply",
"index": "0",
"parameters": [
{
"type": "payload",
"payload": "button-0-payload"
}
]
},
{
"type": "button",
"sub_type" : "quick_reply",
"index": "1",
"parameters": [
{
"type": "payload",
"payload": "button-1-payload"
}
]
}
]
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

For quick reply buttons, it is possible to provide a custom payload for each button. The payload will be part of the incoming message notification that will be sent by WhatsApp whenever the button is clicked.

Start a Turn journey when a template quick reply button is clicked

If you supply a button payload of the form turn-start-journey:JOURNEY-ID-HERE (for example turn-start-journey:8515561e-2e82-431d-b8f3-e4bac8189183), Turn will start the desired Journey when the user clicks on the template quick reply button.

Here is an example that sends a template with quick reply buttons that will start different journeys when clicked:

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "template",
"template": {
"name": "template-name",
"language": {
"code": "en",
"policy": "deterministic"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "body placeholder 1 value"
}
]
},
{
"type": "button",
"sub_type" : "quick_reply",
"index": "0",
"parameters": [
{
"type": "payload",
"payload": "turn-start-journey:018f2df5-3dad-7eb2-b706-8930546a94c6"
}
]
},
{
"type": "button",
"sub_type" : "quick_reply",
"index": "1",
"parameters": [
{
"type": "payload",
"payload": "turn-start-journey:018f2df6-20e0-7354-9f4c-6a3a43daf896"
}
]
}
]
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

Media Templated Messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "template",
"template": {
"namespace": "template-namespace",
"name": "template-name",
"language": {
"code": "en",
"policy": "deterministic"
},
"components": [
{
"type": "header",
"parameters": [
{
"type": "video",
"video": {
"link": "https://url.com/video-file.mp4"
}
}
]
}
]
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

Sending a media templated message simply means sending a templated message using a template that that has a media header. When sending the templated message, the components array of the request object should provide the URL of the media file you intend to send inside its parameters object.

Please refer to the official WhatsApp documentation for more details.

Formatting in Text Messages

WhatsApp allows some formatting in messages. To format all or part of a message, use these formatting symbols:

FormattingSymbolExample
boldAsterisk(*)Your total is *$10.50*.
italicsUnderscore(_)Welcome to WhatsApp!
strikethroughTilde(~)This is better best!
codeThree backticks (```)```print 'Hello World';```

HSM (Deprecated)

caution

Please note that the HSM functionality has been deprecated by WhatsApp. The WhatsApp Business API version 2.31 will be the last one to support this feature. We recommend switching to the new template message format as soon as possible.

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "hsm",

"hsm": {
"namespace": "8bea15c0_b636_0737_7912_63f2b9a6bd09"
"element_name": "purchase_with_credit_card",
"language": {
"policy": "fallback" | "deterministic",
"code": "en_US"
},
"localizable_params": [
{ "default": "$10" },
{ "default": "1234" }
]
}
}'

> {
"messages": [{
"id": "gBEGkYiEB1VXAglK1ZEqA1YKPrU"
}]
}

As with other messages, the message is sent to the /v1/messages endpoint. What's different about sending Message Templates is the content of the message body specified with the hsm parameter.

The hsm parameter contains a namespace and an element_name pair that identify a template and the values to apply to variables in that template.

Additional documentation for:

Localizable Parameters for Templated Messages

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "whatsapp_id",
"type": "hsm",

"hsm": {
"namespace": "8bea15c0_b636_0737_7912_63f2b9a6bd09"
"element_name": "purchase_with_credit_card",
"language": {
"policy": "fallback" | "deterministic",
"code": "en_US"
}
"localizable_params": [
{ "default": "$10" },
{ "default": "1234" }
],
}
}
'

The following code provides an example of sending a Message Template. This example uses the purchase_with_credit_card element name within the 8bea15c0_b636_0737_7912_63f2b9a6bd09 namespace.

The resulting message received by the customer will look like this:

You made a purchase for $10 using a credit card ending in 1234.

As you can see from looking at the localizable parameters and the message the client received, the template used the default value of 10 as the amount of the purchase and the default value of 1234 as the last numbers of the account.

Parameters

NameRequiredDescription
typeyesMust be hsm for templated messages. HSM stands for Highly Structured Messages
toyesThe WhatsApp ID to whom the message is being sent
hsmyesThe containing element for the message content — Indicates that the message is highly structured. Parameters contained within provide the structure. See Parameters for the HSM object for more details.

Parameters for the HSM object

NameRequiredDescription
namespaceyesThe namespace that will be used
element_nameyesThe element name that indicates which template to use within the namespace
languageyesAllows for the specification of a deterministic or fallback language. See the Parameters for the Language object section for more information.

Parameters for the Language object

The language parameter sets the language policy for an Message Template; you can set it to either fallback or deterministic.

NameRequiredDescription
policyyesThe language policy the message should follow. Possible values: fallback or deterministic
codeyesThe code of the language or locale to use — Accepts both language and language_locale formats (e.g., en and en_US).

When sending a Message Template, the hsm object is required. To define Message Templates, you specify a namespace and an element_name pair that identify a template. Templates have parameters that will be dynamically incorporated into the message. For the example used in this document, the Message Template looks like this:

"You made a purchase for {{1}} using a credit card ending in {{2}}."

For "namespace": "8bea15c0_b636_0737_7912_63f2b9a6bd09" with "element_name": "purchase_with_credit_card", the first value you list replaces the {{1}}variable in the template message and the second value you list replaces the {{2}} variable.

caution

Note that the number of parameters passed into the payload must match the number of parameters in the hsm object. If not, you will get a callback informing you that there was an issue displaying the Message Template.

Some of these parameters (e.g., date-time or currency) are localizable so that they are displayed appropriately based on the customer's language and locale preferences. If the device is unsuccessful in localizing a parameter, it will fallback to the value that is provided as the "default" value.

The localizable_params options are shown in the table below. For more information on localizable parameters, read the Localization section.

NameTypeRequiredDescription
defaultStringyesDefault text if localization fails
currencycurrency objectnoIf the currency object is used, it contains required parameters currency_code and amount_1000.
date_timedate_time objectnoIf the date_time object is used, further definition of the date and time is required. See the example below for two of the options.

All of the localization parameters must have a default value. The default value is all that is needed when you are specifying text.

However, to specify currency and date in addition to the default, when applicable, use the currency and date_time objects, as shown below. This will allow the client to attempt to localize this data the best way possible and fallback to the default option only if they cannot localize the data. Note that using the currency and date_time objects for appropriate parameters is highly recommended to enable an optimal localized experience for your customers.

Example Template Localization

The following is a complete example that demonstrates the use of all of the currently supported localized types:

$ curl -X POST https://whatsapp.turn.io/v1/messages \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '
{
"to": "19195551112",
"type": "hsm",
"recipient_type": "individual",

"hsm": {
"namespace": "8bea15c0_b636_0737_7912_63f2b9a6bd09",
"element_name": "four_lparam_demo",
"language": {
"policy": "deterministic",
"code": "en_US"
}

"localizable_params": [
{
"default": "just a string"
},
{
"default": "$100.99",
"currency": {
"currency_code": "USD",
"amount_1000": 100990
}
},
{
"default": "February 25, 1977",
"date_time": {
"component": {
"day_of_week": 5,
"day_of_month": 25,
"year": 1977,
"month": 2,
"hour": 15,
"minute": 33
}
}
},
{
"default": "January 26, 2017",
"date_time": {
"unix_epoch": {
"timestamp": 1485470276
}
}
}
]
}
}
'