We are sunsetting On-Premises API. Refer to our On-Premises API Sunset document for details, and to learn how to migrate to our next-generation Cloud API.
/v1/messages
Use the messages
node to send text, media, contacts, locations, and interactive messages, as well as message templates to your customers.
See the following guides for information regarding the specific types of messages you can send: Text Messages , Media Messages , Contacts and Location Messages , Interactive Messages , Message Templates , Media Message Templates , and Interactive Message Templates .
You need:
Starting in v2.39 and above, you do not have to call the contacts node before sending a message.
You send messages by making a POST
call to the /messages
node regardless of message type. The content of the JSON message body differs for each type of message (text, image, etc.).
These are the main parameters used in /messages
POST requests:
audio
Required when type=audio
.
A media
object
containing audio.
biz_opaque_callback_data
Optional.
An arbitrary string, useful for tracking.
For example, you could pass the message template ID in this field to track your customer's journey starting from the first message you send. You could then track the ROI of different message template types to determine the most effective one.
Any app subscribed to the messages
webhook field on the WhatsApp Business Account can get this string, as it is included in statuses
object
within webhook payloads.
Cloud API does not process this field, it just returns it as part of sent/delivered/read message webhooks.
Maximum 512 characters.
Cloud API only .
contacts
Required when type=contacts
.
A contacts
object
.
context
Required if replying to any message in the conversation.
An object containing the ID of a previous message you are replying to. For example:
{"message_id":"MESSAGE_ID"}
Cloud API only .
document
Required when type=document
.
A media
object
containing a document.
hsm
Contains an hsm
object
. This option was deprecated with v2.39
of the On-Premises API. Use the template
object instead.
On-Premises API only .
image
Required when type=image
.
A media
object
containing an image.
interactive
Required when type=interactive
.
An interactive
object
. The components of each interactive
object generally follow a consistent pattern: header
, body
, footer
, and action
.
location
Required when type=location
.
A location
object
.
messaging_product
preview_url
Required if type=text
.
Allows for URL previews in text messages — See the Sending URLs in Text Messages
. This field is optional if not including a URL in your message. Values: false
(default), true
.
On-Premises API
only. Cloud API users can use the same functionality with the preview_url
field inside a text object
.
recipient_type
Optional.
Currently, you can only send messages to individuals. Set this as individual
.
Default: individual
status
A message's status. You can use this field to mark a message as read
. See the following guides for information:
sticker
Required when type=sticker
.
A media
object
containing a sticker.
Cloud API: Static and animated third-party outbound stickers are supported in addition to all types of inbound stickers. A static sticker needs to be 512x512 pixels and cannot exceed 100 KB. An animated sticker must be 512x512 pixels and cannot exceed 500 KB.
On-Premises API: Only static third-party outbound stickers are supported in addition to all types of inbound stickers. A static sticker needs to be 512x512 pixels and cannot exceed 100 KB. Animated stickers are not supported.
template
Required when type=template
.
A template
object
.
text
Required for text messages.
A text
object
.
to
Required.
WhatsApp ID or phone number of the customer you want to send a message to. See Phone Number Formats .
If needed, On-Premises API users can get this number by calling the contacts
endpoint
.
type
Optional.
The type of message you want to send. If omitted, defaults to text
.
Name | Description |
---|---|
|
Required. Contains the text of the message, which can contain URLs and formatting. |
For the On-Premises API, the media object id is returned when the media is successfully uploaded to the WhatsApp Business on-premises/reference client via the media
endpoint
.
id
Required when type
is audio
, document
, image
, sticker
, or video
and you are not using a link.
The media object ID. Do not use this field when message type
is set to text
.
link
Required when type
is audio
, document
, image
, sticker
, or video
and you are not using an uploaded media ID (i.e. you are hosting the media asset on your public server).
The protocol and URL of the media to be sent. Use onlywith HTTP/HTTPS URLs.
Do not use this field when message type
is set to text
.
Cloud API users only:
Content-Type
HTTP header. For example: Content-Type: video/mp4
. See Supported Media Types
for a list of supported media and their MIME types. caption
Optional.
Media asset caption. Do not use with audio
or sticker
media.
On-Premises API users:
document
media. filename
Optional.
Describes the filename for the specific document. Use onlywith document
media.
The extension of the filename will specify what format the document is displayed as in WhatsApp.
provider
Optional. On-Premises API only.
This path is optionally used with a link
when the HTTP/HTTPS link is not directly accessible and requires additional configurations like a bearer token. For information on configuring providers, see the Media Providers documentation
.
Inside contacts
, you can nest the following objects: addresses
, emails
, name
, org
, phone
, and urls
. Pluralized objects are to be wrapped in an array as shown in the example below.
Name | Description |
---|---|
|
Optional. Full contact address(es) formatted as an |
|
Optional. |
|
Optional. Contact email address(es) formatted as an |
|
Required. Full contact name formatted as a *At least one of the optional parameters needs to be included along with the |
|
Optional. Contact organization information formatted as an |
|
Optional. Contact phone number(s) formatted as a |
|
Optional. Contact URL(s) formatted as a |
Example of a contacts
object with pluralized objects nested inside:
"contacts": [ { "addresses": [ { "city": "city name", "country": "country name", "country_code": "code", "state": "Contact's State", "street": "Contact's Street", "type": "Contact's Address Type", "zip": "Contact's Zip Code" } ], "birthday": "birthday", "emails": [ { "email": "email", "type": "HOME" }, { "email": "email", "type": "WORK" } ], "name": { "first_name": "first name value", "formatted_name": "formatted name value", "last_name": "last name value", "suffix": "suffix value" }, "org": { "company": "company name", "department": "dep name", "title": "title" }, "phones": [ { "phone": "Phone number", "wa-id": "WA-ID value", "type": "MAIN" }, { "phone": "Phone number", "type": "HOME" }, { "phone": "Phone number", "type": "WORK" } ], "urls": [{ "url": "some url", "type": "WORK" }] } ]
Name | Description |
---|---|
|
Required. Location latitude in decimal degrees. |
|
Required. Location longitude in decimal degrees. |
|
Required. Name of the location. |
|
Required. Address of the location. |
Inside template
, you can nest the components
and the language
objects.
Beginning in v2.27.8
, a template's namespace
must be the namespace associated with the WABA that owns the phone number in the current WhatsApp Business on-prem client. Otherwise, the message will fail to send.
In addition, from v2.41
and onwards, namespace
will be an optional field.
Name | Description |
---|---|
|
Required. Name of the template. |
|
Required. Contains a The |
|
Optional. Array of |
|
Optional. Only used for On-Premises API. Namespace of the template. |
Inside components
, you can nest the parameters
object
. Additionally, you can set type
to button
.
type
Required.
Describes the component
type.
Example of a components
object with an array of parameters
object nested inside:
"components": [{ "type": "body", "parameters": [{ "type": "text", "text": "name" }, { "type": "text", "text": "Hi there" }] }]
Supported Options
header
body
button
For text-based templates, we only support the type=body
.
sub_type
Required when type=button
. Not used for the other types.
Type of button to create.
Supported Options
quick_reply
: Refers to a previously created quick reply button that allows for the customer to return a predefined message.url
: Refers to a previously created button that allows the customer to visit the URL generated by appending the text
parameter to the predefined prefix URL in the template.catalog
: Refers to a previously created catalog button that allows for the customer to return a full product catalog. parameters
Required when type=button
.
Array of parameter
objects
with the content of the message.
For components of type=button, see the button
parameter object
.
index
Required when type=button
. Not used for the other types.
Position index of the button. You can have up to 10 buttons using index values of 0 to 9.
Name | Description |
---|---|
|
Required. Describes the Example of a { "type": "text", "text": "Customer" } Example of a { "type": "document", "document":{ "id": "doc_id", "filename": "doc_name" } } This is also known as a Media message template and they only support PDF documents. For more information about |
Inside the components
object
, you can set type
to button
. These are the button parameters:
sub_type
Required.
Type of button being created.
Values: quick_reply
, url
, copy_code (available from 2.49 and onwards)
index
Required.
Position index of the button. You can have up to 10 buttons using index values of 0-9
.
parameters
Required.
The parameters for the button, which are set at creation time in your Business Manager. Include the following parameters:
type
(Required): Indicates the type of parameter for the button. Supported values are payload
, text
and coupon_code
.payload
(Required for quick_reply
buttons): Developer-defined payload that will be returned when the button is clicked in addition to the display text on the button.text
(Required for url
buttons): Developer provided suffix that will be appended to a previously created dynamic URL button.coupon_code
(Required for copy_code buttons) (available from 2.49 and onwards): Developer provided coupon code which gets copied when the copy code button is clicked.Example of button
type with sub_type quick_reply
:
{ "type": "button", "sub_type": "quick_reply", "index": 0, "parameters": [{ "type": "payload", "payload": "Yes-Button-Payload" }] }
Example of button
type with sub_type copy_code
{ "type": "button", "sub_type": "copy_code", "index": 0, "parameters": [{ "type": "coupon_code", "coupon_code": "DISCOUNT20" }] }
The hsm
object has been deprecated with v2.39
of the WhatsApp Business on-premises/reference
. Please use the template
object instead.
Name | Description |
---|---|
|
Required. The namespace to be used. Beginning with |
|
Required. The element name that indicates which template to use within the namespace. Beginning with |
|
Required. Allows for the specification of a deterministic language. See the Language section for more information. This field used to allow for a |
|
Required. This field is an array of values to apply to variables in the template. See the Localizable Parameters section for more information. |
The interactive
object generally contains 4 main components: header
, body
, footer
, and action
. Additionally, some of those components can contain one or more different objects:
header
, you can nest media
objects.action
, you can nest section
and button
objects. type
Required.
The type of interactive message you want to send. Supported values:
list
: Use it for List Messages.button
: Use it for Reply Buttons.product
: Use it for Single-Product Messages.product_list
: Use it for Multi-Product Messages.catalog_message
: Use it for Catalog Messages.flow
: Use it for Flows Messages. header
Required for type product_list
. Optional for other types.
Header content displayed on top of a message. You cannot set a header
if your interactive
object is of product
type.
The header
object contains the following fields:
document
object
– Required if type
is set to document
.
Contains the media
object with the document.
image
object
– Required if type
is set to image
.
Contains the media
object with the image.
video
object
– Required if type
is set to video
.
Contains the media
object with the video.
text
string
– Required if type
is set to text
.
Text for the header. Formatting allows emojis, but not markdown. Maximum length: 60 characters.
type
string
– Required.
The header type you would like to use. Supported values are:
text
– for List Messages, Reply Buttons, and Multi-Product Messages.
video
– for Reply Buttons.
image
– for Reply Buttons.
document
– for Reply Buttons.
body
Optional for type product
. Required for other message types.
An object with the body of the message.
The body
object contains the following field:
text
string
– Required if body is present.
The content of the message. Emojis and markdown are supported. Maximum length: 1024 characters.
footer
Optional.
An object with the footer of the message.
The footer
object contains the following field:
text
string
– Required if footer is present.
The footer content. Emojis, markdown, and links are supported. Maximum length: 60 characters.
action
Required.
An action
object with what you want the user to perform after reading the message. See action
object
for full information.
Name | Description |
---|---|
|
Required for List Messages. Button content. It cannot be an empty string and must be unique within the message. Emojis are supported, markdown is not. Maximum length: 20 characters. |
|
Required for Reply Button Messages. A You cannot have leading or trailing spaces when setting the ID. |
|
Required for List Messages and Multi-Product Messages. Array of |
|
Required for Single-Product Messages and Multi-Product Messages. Unique identifier of the Facebook catalog linked to your WhatsApp Business Account. This ID can be retrieved via Commerce Manager. |
|
Required for Single-Product Messages and Multi-Product Messages. Unique identifier of the product in a catalog. Maximum 100 characters for both Single-Product and Multi-Product messages. To get this ID, go to Commerce Manager , select your Facebook Business account, and you will see a list of shops connected to your account. Click the shop you want to use. On the left-side panel, click Catalog> Items, and find the item you want to mention. The ID for that item is displayed under the item's name. |
|
Optional for Flows Messages. The current mode of the Flow, either Default: |
|
Required for Flows Messages. Must be |
|
Required for Flows Messages. A token that is generated by the business to serve as an identifier. |
|
Required for Flows Messages. Unique identifier of the Flow provided by WhatsApp. |
|
Required for Flows Messages. Text on the CTA button, eg. "Signup". Maximum length: 20 characters (no emoji). |
|
Optional for Flows Messages. Default: |
|
Optional for Flows Messages. Required only if |
Name | Description |
---|---|
|
Required if the message has more than one Title of the section. Maximum length: 24 characters. |
|
Required for List Messages. Contains a list of row objects. Limited to 10 rows across all sections. Each |
|
Required for Multi-Product Messages. Array of Each |
Audio messages:
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "audio", "audio": { "id": " your-media-id ", } }
Document messages, using filename
:
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "document", "document": { "id": " your-media-id ", "filename": " your-document-filename " } }
Document messages, using link
:
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "document", "document": { "link": "http(s):// the-url " "provider": { "name" : " provider-name " } } }
Video messages, using link
:
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "video", "video": { "link": "http(s):// the-url " "provider": { "name" : " provider-name " } } } }
Text messages:
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "text", "text": { "body": " your-message-content " } }
Interactive messages (lists):
POST /v1/messages { "recipient_type": "individual", "to": "whatsapp-id", "type": "interactive", "interactive":{ "type": "list", "header": { "type": "text", "text": "your-header-content-here" }, "body": { "text": "your-text-message-content-here" }, "footer": { "text": "your-footer-content-here" }, "action": { "button": "cta-button-content-here", "sections":[ { "title":"your-section-title-content-here", "rows": [ { "id":"unique-row-identifier-here", "title": "row-title-content-here", "description": "row-description-content-here", } ] }, { "title":"your-section-title-content-here", "rows": [ { "id":"unique-row-identifier-here", "title": "row-title-content-here", "description": "row-description-content-here", } ] }, ... ] } } }
Interactive messages (reply buttons):
POST /v1/messages { "recipient_type": "individual", "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" } } ] } # end action } # end interactive }
Interactive messages (Multi and Single-Product Messages):
{ "recipient_type": "individual", "to" : "{{Recipient-WA-ID}}", "type": "interactive", "interactive": { "type": "product", "body": { "text": "body text" }, "footer": { "text": "footer text" }, "action": { " _id": "catalog-ID", "product_retailer_id": "product-ID" } } }
Interactive messages (Multi-Product Messages):
{ "recipient_type": "individual", "to" : "whatsapp-id", "type": "interactive", "interactive": { "type": "product_list", "Header":{ "type": "text", "text": "text-header-content" }, "body":{ "text": "text-body-content" }, "footer":{ "text":"text-footer-content" }, "action":{ "catalog_id":"catalog-id", "sections": [ { "title": "section-title", "product_items": [ { "product_retailer_id": "product-SKU-in-catalog" }, { "product_retailer_id": "product-SKU-in-catalog" }, ... ]}, { "title": "the-section-title", "product_items": [ { "product_retailer_id": "product-SKU-in-catalog" } ... ]}, ... ] }, } }
Interactive messages (Catalog Messages):
{ "recipient_type": "individual", "to" : "whatsapp-id", "type": "interactive", "interactive": { "type": "catalog_message", "body":{ "text": "text-body-content" }, "footer":{ "text":"text-footer-content" }, "action":{ "name": "catalog_message", "parameters":{ "thumbnail_product_retailer_id": "product-SKU-in-catalog" } }, } }
Interactive messages (Flows):
{ "recipient_type": "individual", "to": "{{Recipient-WA-ID}}", "type": "interactive", "interactive": { "type": "flow", "header": { "type": "text", "text": "Flow message header" }, "body": { "text": "Flow message body" }, "footer": { "text": "Flow message footer" }, "action": { "name": "flow", "parameters": { "flow_message_version": "3", "flow_token": "AQAAAAACS5FpgQ_cAAAAAD0QI3s", "flow_id": "<FLOW_ID>", "flow_cta": "Book!", "flow_action": "navigate", "flow_action_payload": { "screen": "<SCREEN_ID>", "data": { # optional "user_name": "name", "user_age": 25 } } } } } }
The following shows an example of payload
in a response; the meta and error objects are omitted for brevity.
{ "messages": [{ "id": " message-id " }] }
If the request is successful, you receive a response with a message ID. If the request returns an errors
section, check the originating message and correct the errors before resending the request. For more information about errors, see WhatsApp Business on-premises/reference Client Error Codes
and HTTP Status Codes
.
Applies to businesses in Brazil, Colombia, and Singapore, starting September 12, 2023. Applies to all businesses starting October 12, 2023.
If the request is held for quality assessment, the response will contain a message_status
property with a message indicating that the message was not sent immediately and will be sent or dropped after quality has been validated. This property will only exist if the message is held.
{ "messages": [{ "id": " message-id ", "message_status": "Message has been held because quality assessment is pending", }] }
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 ~better~ best! |
|
Three backticks (```) |
```print 'Hello World';``` |
In this context, performance represents the number of messages that can be sent in any given second using the WhatsApp Business on-premises/reference client. The maximum achievable performance depends on a variety of factors, the most important factor being your client setup choice and whether a message is being sent to a new user or an existing user —encryption sessions setup take a little longer when messaging a new user.
Client Setup | Supported Text Messages Per Second |
---|---|
Single Shard |
70 |
Multi Shard (32 shards) |
250 |
Note:Please do not send the same message repeatedly to the same recipient using the WhatsApp Business API.
There can be multiple reasons why delivery rates are not 100%. Some common cases include users having sporadic access to network, being inactive for a period of time, or to create a high quality user experience .
Messages that can be delivered with WhatsApp will have a very high delivery rate. However there are many reasons why a message may not be delivered. You will have access to the exact status of a message by monitoring your callbacks. This is different from sending messages with SMS, for example, where you do not have access to final delivered status and resending the message may indeed produce a different outcome.
Messages may remain undelivered because a user's phone is out of service, or battery, or they have lost it and are getting a new one and have disabled their SIM. It is possible there are errors in the business client's ability to connect to the network. It is also possible callbacks (Webhooks) are not being delivered. You can monitor these situations by using the health
node. You can turn on server receipt callbacks to know that the message made it into the WhatsApp server cloud.
If and when a user does reconnect to the network all the messages you sent will be delivered to them. Receiving more than one message with the same content will be a bad experience for them. They will be more likely to block you or complain. You will be more likely to be banned.
If you send a message and receive a message ID from the API, you have done what you can to send this message. Do not resend the same content to the same recipient.
If you are seeing low delivery rates over a prolonged period of time, please file a support ticket with Direct Support .
When you send a message, as soon as you get back a message ID, that means the message request has been stored on the database. The WhatsApp Business API Client will keep attempting to send that message until acknowledged by the WhatsApp server. This process has no end timeline. The WhatsApp server will then try to deliver that message to the user's phone. If the user's phone is not online, the message will be stored for 30 days before being discarded by the WhatsApp server.
Yes! WhatsApp allows you to format selected text inside your messages with Bold, Italics, Strikethrough or Monospace.
Currently, there is no way to see how many or which users have blocked your business. The best indicator would be to listen for status callbacks and if you do not receive the delivered
status, then either the user has blocked your business or they do not have a network connection. See the Webhook
documentation for more details.
If a user has blocked your business, the Contacts API will continue to return that phone number as a valid WhatsApp user. However, when you send the message, it will never get delivered. If it is a paid message, you will not be charged.
No, the order in which the messages arrive is not guaranteed to be the same order as what was sent. If ordering is critical to your use case, the suggested approach is to listen for the delivered callback of the first message before firing the second message.
When using the messages
node, you need to set the Content-Type
header to application/json
for the WhatsApp Business API Client to properly parse the message body. There is also an Authorization
header that needs to be set and must contain an unexpired access token. See the Login and Authentication
documentation for information on how to get your token and when it expires.
There may be cases where you need more time to handle a customer query and may only be able to provide a response after 24 hours. We recommend creating message templates to either:
In both cases, please ensure you provide as much context to the message template as possible. For example: