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.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.

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 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://.
toconditionalThe WhatsApp ID (phone number) of the recipient. Required if recipient is not provided.
recipientconditionalThe BSUID of the recipient (e.g. US.13491208655302741918). Required if to is not provided.
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

NameRequiredDefaultDescriptionOptions
toconditionalThe WhatsApp ID (phone number) of the recipient. Required if recipient is not provided.
recipientconditionalThe BSUID of the recipient. Required if to is not provided.
typeyesnotextOptions: text, image, audio, document, sticker
<media-type>.idThe media object ID, which is returned when the media is successfully uploaded to the WhatsApp Business API Client with the media endpoint.
<media-type>.captionDescribes 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.

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.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

Alpha Release

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:

ComponentDescription
bodyA text parameter with the OTP code, replacing the {{1}} placeholder in the template body.
buttonA 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.
caution

If you get an error like OAuthException: Invalid parameter when sending an authentication template, it usually means:

  • The sub_type doesn't match the button type in the template (e.g. using "quick_reply" instead of "url")
  • The button parameters are missing or malformed
  • The index doesn'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:

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

HSM (Removed)

caution

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.