Interactive Messages
Interactive messages let customers choose buttons or list items. Send the complete request bodies below to the corresponding channel send endpoint with x-api-key and Content-Type: application/json. Replace channel IDs, recipient IDs and example media URLs with your own values. Ordinary WhatsApp interactive sends require an active 24-hour customer-service window.
WhatsApp session limits
These limits apply to ordinary WhatsApp interactive messages, without a template. Each message uses one interactive type; template button limits do not apply to session messages.
| Interactive type | Quantity per message | Label limits |
|---|---|---|
button | 1–3 reply buttons | Reply title: 20 characters; reply ID: 256 characters |
cta_url | 1 URL button | action.parameters.display_text: 20 characters |
list | 1 button opening 1–10 options in total, across 1–10 sections | Opening button: 20 characters; section/row title: 24; row description: 72; row ID: 200 |
The list's ten-option limit counts all rows across all sections, not ten rows per section. A button message accepts only reply buttons; it cannot combine replies with a URL CTA. Send separate session messages or use an approved template with a supported button combination.
These are WhatsApp provider limits, not a guarantee that Hub rejects every oversized payload before forwarding it. Hub's shared nested-array validation ceiling of 100 entries does not increase WhatsApp's supported quantities, and other channels have their own limits.
The current Hub API accepts button, list, cta_url and location_request_message as content.interactive.type. Meta's voice_call and interactive carousel formats are not accepted by this field. Template Flow buttons use the separate template contract.
See Meta's references for reply buttons, CTA URL messages and lists.
Availability by type and channel
| Interactive type | Messenger | Telegram | Web Chatt | ||
|---|---|---|---|---|---|
| Quick Reply (buttons) | Yes | Yes | Yes | Inline keyboard | Yes |
| Option list | Yes | Cards | Cards | Poll | Yes |
| CTA URL | Yes | URL button | URL button | No | Yes |
| Request location | Yes | No | No | No | No |
Web Chatt widget v1.3.1 implements buttons, lists and CTA URL navigation. It also renders text/image/video headers and footers for buttons and CTA messages. This is the verified local widget version; older widget versions may differ. The document header is described separately below. These are implementation capabilities; provider acceptance and client presentation can vary.
Instagram and Messenger discard interactive headers and footers. Telegram supports image/video headers on buttons and appends the footer to the message caption. WhatsApp passes supported headers and footers to the provider.
Quick Reply (response buttons)
The three-button limit applies to WhatsApp, as do the 20-character reply titles below. Instagram and Messenger use the quick-reply transformation for 1–13 buttons without an image/video header; media headers select a different button-template transformation and are discarded. Telegram and Web Chatt do not share WhatsApp's three-button limit. Hub nested arrays accept at most 100 entries; that validation ceiling does not replace provider limits.
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "button",
"header": {
"type": "text",
"text": "Customer support"
},
"body": {
"text": "How can I help you?"
},
"footer": {
"text": "Reply with an option"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "SUPPORT",
"title": "Support"
}
},
{
"type": "reply",
"reply": {
"id": "SALES",
"title": "Sales"
}
},
{
"type": "reply",
"reply": {
"id": "OTHER",
"title": "Other"
}
}
]
}
}
}
}
| Field | Use |
|---|---|
action.buttons[].type | reply |
reply.id | Your callback identifier |
reply.title | Display label; use at most 20 characters for WhatsApp |
Image header on Telegram buttons
Use POST /v1/communication/telegram/message with a Telegram bot channel UUID and chat ID. The image becomes a photo with an inline keyboard; the body and footer form its caption.
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "123456789",
"content": {
"interactive": {
"type": "button",
"header": {
"type": "image",
"image": {
"link": "https://example.com/support-banner.jpg"
}
},
"body": {
"text": "How can I help you?"
},
"footer": {
"text": "Reply with an option"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "SUPPORT",
"title": "Support"
}
},
{
"type": "reply",
"reply": {
"id": "SALES",
"title": "Sales"
}
},
{
"type": "reply",
"reply": {
"id": "OTHER",
"title": "Other"
}
}
]
}
}
}
}
For WhatsApp and Web Chatt, the same interactive object can use an image header or a video header with type: "video" and video.link. Use the appropriate channel UUID and recipient ID at that channel's send endpoint. Web Chatt recipients are visitor UUIDs, for example 74f7d0c4-a11d-4c1d-9569-17757aac1832.
Video header on Web Chatt buttons
Use POST /v1/communication/web-chatt2me/message with a widget channel and visitor UUID. Widget v1.3.1 renders the video header, body, footer and reply buttons:
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "74f7d0c4-a11d-4c1d-9569-17757aac1832",
"content": {
"interactive": {
"type": "button",
"header": {
"type": "video",
"video": {
"link": "https://example.com/support-introduction.mp4"
}
},
"body": {
"text": "How can I help you?"
},
"footer": {
"text": "Reply with an option"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "SUPPORT",
"title": "Support"
}
},
{
"type": "reply",
"reply": {
"id": "SALES",
"title": "Sales"
}
},
{
"type": "reply",
"reply": {
"id": "OTHER",
"title": "Other"
}
}
]
}
}
}
}
Option list
WhatsApp and Web Chatt preserve the section/row structure. Instagram and Messenger flatten the rows into cards with postback buttons, losing section grouping. Telegram converts the row titles into a poll and requires at least two nonempty option titles. Sections, descriptions and row IDs are not represented in that poll.
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "list",
"header": {
"type": "text",
"text": "Our menu"
},
"body": {
"text": "Choose a dish"
},
"footer": {
"text": "Available until 10 PM"
},
"action": {
"button": "View options",
"sections": [
{
"title": "Main courses",
"rows": [
{
"id": "dish_1",
"title": "Grilled steak",
"description": "With fries and salad"
},
{
"id": "dish_2",
"title": "Shrimp risotto",
"description": "Serving for 2 people"
}
]
},
{
"title": "Desserts",
"rows": [
{
"id": "dessert_1",
"title": "Chocolate lava cake",
"description": "With vanilla ice cream"
}
]
}
]
}
}
}
}
| Field | Use |
|---|---|
action.button | Label that opens the WhatsApp list |
action.sections | Sections containing rows |
sections[].title | Optional section heading |
rows[].id | Callback identifier for channels that preserve row IDs |
rows[].title | Item label; use at most 24 characters for WhatsApp |
rows[].description | Optional description; use at most 72 characters for WhatsApp |
On Telegram, use action.name: "multiple" or "multiple_answers" for multiple selections; the default poll mode is regular. A provider may impose additional poll limits. Use unique titles if your integration needs to recognize selections from their text.
CTA URL (button with external link)
A CTA opens a browser URL. It is supported by WhatsApp, Instagram, Messenger and the Web Chatt widget described above. Telegram has no CTA transformation. Opening a CTA does not provide the button/list selection webhook shown below.
Text header
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "cta_url",
"header": {
"type": "text",
"text": "Visit our website"
},
"body": {
"text": "Open your order details."
},
"footer": {
"text": "Available 24/7"
},
"action": {
"parameters": {
"display_text": "View order",
"url": "https://example.com/orders/order-123"
}
}
}
}
}
Image header
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "cta_url",
"header": {
"type": "image",
"image": {
"link": "https://example.com/order-banner.jpg"
}
},
"body": {
"text": "Open your order details."
},
"footer": {
"text": "Available 24/7"
},
"action": {
"parameters": {
"display_text": "View order",
"url": "https://example.com/orders/order-123"
}
}
}
}
}
Video header
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "cta_url",
"header": {
"type": "video",
"video": {
"link": "https://example.com/order-demo.mp4"
}
},
"body": {
"text": "Open your order details."
},
"footer": {
"text": "Available 24/7"
},
"action": {
"parameters": {
"display_text": "View order",
"url": "https://example.com/orders/order-123"
}
}
}
}
}
Document header
Use a document header for a compatible WhatsApp connection. The link must be an HTTP(S) URL; the optional filename is nonempty and limited to 255 characters. Hub validates and prepares the document media before forwarding it; WhatsApp documents have a 100 MiB limit. See Content Types for media requirements.
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "cta_url",
"header": {
"type": "document",
"document": {
"link": "https://example.com/order-summary.pdf",
"filename": "Order-summary.pdf"
}
},
"body": {
"text": "Open your order details."
},
"footer": {
"text": "Available 24/7"
},
"action": {
"parameters": {
"display_text": "View order",
"url": "https://example.com/orders/order-123"
}
}
}
}
}
This new API header type does not imply document-preview rendering in Web Chatt widget v1.3.1 or other clients. Instagram/Messenger discard the header, and Telegram has no CTA transformation. Verify presentation in your target WhatsApp client.
Request user location (WhatsApp)
{
"from": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f",
"to": "5511993986082",
"content": {
"interactive": {
"type": "location_request_message",
"body": {
"text": "To calculate shipping, please share your location."
},
"action": {
"name": "send_location"
}
}
}
}
The reply arrives as a location message in the normalized webhook payload.
User responses via webhook
Hub sends its normalized message envelope. Read the selected identifier from payload.message.content.buttons[].id, the displayed title from label, and the incoming Hub message ID from payload.message.id.
WhatsApp button selection
{
"eventType": "message",
"timestamp": "2026-10-06T15:00:00.000Z",
"payload": {
"provider": "whatsapp",
"direction": "IN",
"timestamp": 1791298800000,
"message": {
"id": "9b509e32-bfec-4fe6-8a63-2c22017a3a17",
"sessionId": "d387b2bf-b36e-40f4-90f8-0a4db8a49f75",
"type": "Button",
"content": {
"buttons": [
{
"id": "SUPPORT",
"label": "Support",
"type": "reply"
}
]
}
},
"sender": {
"id": "5511993986082"
},
"recipient": {
"id": "551130001234",
"applicationChannelId": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f"
}
}
}
WhatsApp list selection
{
"eventType": "message",
"timestamp": "2026-10-06T15:00:00.000Z",
"payload": {
"provider": "whatsapp",
"direction": "IN",
"timestamp": 1791298800000,
"message": {
"id": "9b509e32-bfec-4fe6-8a63-2c22017a3a17",
"sessionId": "d387b2bf-b36e-40f4-90f8-0a4db8a49f75",
"type": "Button",
"content": {
"buttons": [
{
"id": "dish_1",
"label": "Grilled steak",
"type": "list"
}
]
}
},
"sender": {
"id": "5511993986082"
},
"recipient": {
"id": "551130001234",
"applicationChannelId": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f"
}
}
}
Instagram/Messenger postbacks use buttons[].type: "postback". Handle the normalized fields rather than assuming the provider's raw interactive structure.
Telegram poll selection
The following is a normalized poll-answer envelope when a selected title has been resolved. content.poll.id is the provider poll identifier. Poll aggregate updates may also include question/options/vote counts. Hub does not export the stored selected option indices or list row IDs in this webhook.
{
"eventType": "message",
"timestamp": "2026-10-06T15:00:00.000Z",
"payload": {
"provider": "telegram",
"direction": "IN",
"timestamp": 1791298800000,
"message": {
"id": "9b509e32-bfec-4fe6-8a63-2c22017a3a17",
"sessionId": "d387b2bf-b36e-40f4-90f8-0a4db8a49f75",
"type": "Poll",
"content": {
"text": "Grilled steak",
"poll": {
"id": "5812298937489215487"
}
}
},
"sender": {
"id": "123456789"
},
"recipient": {
"id": "123456789",
"applicationChannelId": "9e85226d-a104-4c85-a21a-5c3cbf7daa8f"
}
}
}
Correlate with the poll ID and resolved title text when available. A poll update without text does not identify an individual selection.