Messages
https://whatsapp.turn.io/v1/messages
This endpoint responsible for sending messages via WhatsApp. Messages for WhatsApp are classified as:
Turn.io's outbound messaging API is synchronous to the upstream gateways. If Turn.io returns with a success response, the upstream gateway has accepted the message for delivery. Turn.io does not queue outbound messaging.
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
tokenwith 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
| Parameter | Required | Default | Description |
|---|---|---|---|
| preview_url | no | false | Specifying preview_url in the request is optional when 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://. |
| to | conditional | The WhatsApp ID (phone number) of the recipient. Required if recipient is not provided. | |
| recipient | conditional | The BSUID of the recipient (e.g. US.13491208655302741918). Required if to is not provided. | |
| type | no | text | Specifying type in the request is optional when you are sending a text message. |
| text.body | yes | The 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 | Options |
|---|---|---|---|---|
| to | conditional | The WhatsApp ID (phone number) of the recipient. Required if recipient is not provided. | ||
| recipient | conditional | The BSUID of the recipient. Required if to is not provided. | ||
| type | yes | no | text | Options: text, image, audio, document, 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.io 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.
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.io 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"
}]
}
Start a Turn.io journey when an interactive reply button is clicked
This API is still in alpha and subject to change. Features, endpoints, and data structures may be modified or removed in future releases.
Similar to template quick reply buttons, you can start a journey when a contact clicks an interactive reply button. Set the button's id to turn-start-journey:JOURNEY-ID-HERE.
For example, to send two reply buttons that each start a different journey:
$ 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",
"body": {
"text": "How can we help?"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "turn-start-journey:018f2df5-3dad-7eb2-b706-8930546a94c6",
"title": "Sales"
}
},
{
"type": "reply",
"reply": {
"id": "turn-start-journey:018f2df6-20e0-7354-9f4c-6a3a43daf896",
"title": "Support"
}
}
]
}
}
}'
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": {
"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.io 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.io 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": {
"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": "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.
Authentication Templated Messages
Authentication templates are used to send one-time passwords (OTP) or verification codes.
The example below sends a template named verification_code whose body contains *{{1}}* is your verification code... and has a single URL-type "Copy code" button with {{1}} in the URL. See Listing Message Templates for the full template definition.
$ 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": "verification_code",
"language": {
"code": "en",
"policy": "deterministic"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "123456"
}
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [
{
"type": "text",
"text": "123456"
}
]
}
]
}
}'
> {
"messages": [{
"id": "wamid.HBgNNTUyMTk5NjE2NTQxORUCABEYEjU0MUVERTBENDNCMzZCQjZDQwA="
}]
}
The components array:
| Component | Description |
|---|---|
body | A text parameter with the OTP code, replacing the {{1}} placeholder in the template body. |
button | A text parameter with the OTP code. The sub_type must be "url" and index must be "0", matching the button defined in the template. The code replaces the {{1}} placeholder in the button URL. |
If you get an error like OAuthException: Invalid parameter when sending an authentication template, it usually means:
- The
sub_typedoesn't match the button type in the template (e.g. using"quick_reply"instead of"url") - The button
parametersare missing or malformed - The
indexdoesn't match the button position
Use the Listing Message Templates endpoint to verify your template's button types before building the send request.
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:
| Formatting | Symbol | Example |
|---|---|---|
| bold | Asterisk(*) | Your total is *$10.50*. |
| italics | Underscore(_) | Welcome to WhatsApp! |
| Tilde(~) | This is | |
code | Three backticks (```) | ```print 'Hello World';``` |
HSM (Removed)
The legacy HSM message format was deprecated and removed by WhatsApp, and support
for it has been removed from this API. Requests with "type": "hsm" are rejected.
Use the template message format instead.