Supported message types
Updated: Aug 13, 2026
Copy for LLM
Direct Send supports text and several interactive message types. For every type, remember to add
"category": "utility" (or "authentication" where supported) to the request body to invoke Direct Send.Interactive message headers can be
text, image, video, or document. See Media message headers for details.Text messages
Text messages contain a text body and an optional link preview.
Note. Thepreview_urlfield is not currently supported. Messages sent with Direct Send do not render a URL preview.
Add
"category": "utility" or "category": "authentication" to the bottom of your request body to invoke Direct Send.Call-to-action (CTA) URL button messages map a URL to a button, so you don’t include the raw URL in the message body. We recommend the combined CTA URL and reply button format instead — see Interactive button messages with CTA URL or reply buttons.
Reply button messages let you send up to three predefined replies for the user to choose from. Selecting a button triggers a messages webhook describing the user’s choice.
Sending a reply button and receiving the tap use different formats.
Direct Send delivers your message as a template, so a reply button tap arrives in the template quick-reply format: top-level
"type": "button" with a button object. It does not arrive as "type": "interactive" with an interactive.button_reply object, which is the format used for free-form Cloud API interactive messages.Read the button label from
button.text. If your integration reads interactive.button_reply.title, it finds no value, because that object isn’t present.The
messages entry looks like this:{ "context": { "from": "<BUSINESS_DISPLAY_PHONE_NUMBER>", "id": "<WHATSAPP_MESSAGE_ID_OF_THE_MESSAGE_YOU_SENT>" }, "from": "<WHATSAPP_USER_PHONE_NUMBER>", "id": "<WHATSAPP_MESSAGE_ID>", "timestamp": "<WEBHOOK_TRIGGER_TIMESTAMP>", "type": "button", "button": { "payload": "<BUTTON_ID>", "text": "<BUTTON_LABEL>" } }
| Field | Description |
|---|---|
type | Always button for a reply button tap. |
button.text | The label of the button the user tapped. |
button.payload | The id you set on the reply button when you sent the message. |
context.id | The ID of the Direct Send message that contained the button. Use it to correlate the reply with the message you sent. |
For the surrounding envelope —
metadata, contacts, and the entry wrapper — see the button messages webhook reference. That reference shows the same value in payload and text. With Direct Send the two differ, because payload carries the button id you set.This is the recommended way to send interactive buttons. You can mix call-to-action URL and reply buttons in the same message:
- Up to 10 buttons total.
- A maximum of 2 CTA buttons.
- CTA buttons are always listed before reply buttons.
Reply buttons in a mixed-button message behave the same way on tap as they do in a reply button message — see Reply button taps use the template webhook format.
The WhatsApp voice call (“Call on WhatsApp”) button lets a WhatsApp user tap to start a WhatsApp voice call to your business phone number. To send it, send a free-form interactive message with a top-level
"category": "utility" and a single voice call button. The display_text and ttl_minutes you provide are applied to the voice call button.Prerequisites
Before you can send a voice call button, enable calling on your business phone number (see the WhatsApp Business Calling prerequisites):
- Subscribe your app to the
callswebhook field for the WhatsApp Business Account. - Enable calling: send
POST /<WHATSAPP_BUSINESS_PHONE_NUMBER_ID>/settingswith{"calling": {"status": "ENABLED"}}.
If calling isn’t enabled, the send fails with error
138000 (Calling API not enabled). If the required calls webhook subscription is missing, enabling calling returns error 138018 (technical prerequisites not met).Availability
The voice call (“Call on WhatsApp”) button is user-initiated — the WhatsApp user taps to call your business. The regional restrictions that apply to business-initiated calling don’t apply to this button. For current availability, see the WhatsApp Business Calling documentation.
Example request
POST /<WHATSAPP_BUSINESS_PHONE_NUMBER_ID>/messages { "messaging_product": "whatsapp", "recipient_type": "individual", "to": "<WHATSAPP_USER_PHONE_NUMBER>", "type": "interactive", "category": "utility", "interactive": { "type": "voice_call", "body": { "text": "Call our support team for help with your order." }, "action": { "name": "voice_call", "parameters": { "display_text": "Call Support", "ttl_minutes": 1440 } } } }
Parameters
| Parameter | Required | Description |
|---|---|---|
interactive.type | Yes | Must be voice_call. |
interactive.body.text | Yes | Message body. Maximum 1024 characters. |
interactive.header | No | Text header only. Maximum 60 characters. Footers aren’t supported for voice call messages. |
action.name | Yes | Must be voice_call. |
action.parameters.display_text | No | Button label. Maximum 20 characters. Defaults to Call on WhatsApp when omitted. |
action.parameters.ttl_minutes | No | 1 to 43200 (1 minute to 30 days). Defaults to 7 days. The button grays out after it expires. |
Limits and behavior
- Exactly one voice call button per message, sent on its own; it can’t be combined with CTA URL or reply buttons in the same message.
- A footer isn’t allowed on voice call messages.
- A
ttl_minutesvalue outside 1 to 43200 returns HTTP400error code100.
Message success and pricing
The message-success webhook payload is at parity with the current Cloud API message-status webhook and includes pricing details. See the webhook statuses object and per-message pricing webhooks for the latest structure.
Direct Send adds one field to the status webhook:
template_id, the template used to send the Direct Send message. It appears in the statuses section:{ "object": "whatsapp_business_account", "entry": [ { "id": "<ID>", "changes": [ { "value": { "messaging_product": "whatsapp", "statuses": [ { "id": "<ID>", "status": "<read/delivered/sent>", "timestamp": "<EPOCH_TIME>", "recipient_id": "<RECIPIENT_PHONE_NUMBER>", "template_id": "<TEMPLATE_ID>", "conversation": { }, "pricing": { } } ] }, "field": "messages" } ] } ] }
Note.recipient_idis the message recipient’s identifier — a phone number, or a business-scoped user ID (BSUID) if the message was addressed to one. See Business-scoped user IDs.