Skip to main content

Interactive Messages

Interactive messages let you present customers with structured choices -- buttons for quick replies or lists for browsable menus. These are supported across multiple channels through a single unified API.

Required Scopes​

ScopePurpose
messages:createSend interactive messages

Channel Capabilities​

Not all channels support all interactive features. Check before sending:

FeatureWhatsAppMessengerInstagramTelegramSMSEmailLive Chat
ButtonsYes (3 max)YesYesYesNoNoYes
ListYesNoNoNoNoNoYes
tip

Use the Channel Capabilities endpoint (GET /api/v1/channels/{channel_id}/capabilities) to programmatically check what a specific channel supports before sending.

Button Messages​

Button messages present up to 3 quick-reply options that customers can tap.

POST /api/v1/messages/send/interactive

Request Body​

FieldTypeRequiredDescription
channel_idstringYesThe channel to send through
contact_idstringYesThe recipient contact
typestringYesMust be buttons
headerobjectNoOptional header (text, image, video, or document)
bodystringYesMain message text. Must contain at least one non-whitespace character
footerstringNoFooter text (smaller, muted)
buttonsarrayYesArray of button objects (max 3)

Each button object:

FieldTypeRequiredDescription
idstringYesUnique button identifier (returned when customer taps)
titlestringYesButton label (max 20 characters)

curl​

curl -X POST "https://api.sendseven.com/api/v1/messages/send/interactive" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "channel_wa_001",
"contact_id": "contact_xyz789",
"type": "buttons",
"header": {
"type": "text",
"text": "Order Support"
},
"body": "How can we help you with your order?",
"footer": "Reply within 24 hours",
"buttons": [
{"id": "track_order", "title": "Track My Order"},
{"id": "return_item", "title": "Return an Item"},
{"id": "speak_agent", "title": "Speak to Agent"}
]
}'

Python​

import requests

BASE_URL = "https://api.sendseven.com/api/v1"
HEADERS = {
"Authorization": "Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00",
"Content-Type": "application/json",
}

response = requests.post(
f"{BASE_URL}/messages/send/interactive",
headers=HEADERS,
json={
"channel_id": "channel_wa_001",
"contact_id": "contact_xyz789",
"type": "buttons",
"body": "Was your issue resolved?",
"buttons": [
{"id": "yes", "title": "Yes, thank you!"},
{"id": "no", "title": "No, I need more help"},
],
},
)
print(response.json())

Response​

{
"id": "msg_int_001",
"conversation_id": "conv_abc123",
"contact_id": "contact_xyz789",
"channel_id": "channel_wa_001",
"type": "interactive",
"interactive_type": "buttons",
"status": "sent",
"created_at": "2026-02-10T17:00:00Z"
}

List Messages​

List messages display a menu with categorized options that customers can browse and select from. These are ideal for presenting multiple choices organized by category.

info

List messages are currently supported on WhatsApp and Live Chat only.

Request Body​

FieldTypeRequiredDescription
channel_idstringYesThe channel to send through
contact_idstringYesThe recipient contact
typestringYesMust be list
bodystringYesMain message text. Must contain at least one non-whitespace character
button_textstringYesText on the button that opens the list
sectionsarrayYesArray of section objects

Each section object:

FieldTypeRequiredDescription
titlestringYesSection heading
rowsarrayYesArray of row items

Each row object:

FieldTypeRequiredDescription
idstringYesUnique row identifier
titlestringYesRow title (max 24 characters)
descriptionstringNoRow description (max 72 characters)

curl​

curl -X POST "https://api.sendseven.com/api/v1/messages/send/interactive" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "channel_wa_001",
"contact_id": "contact_xyz789",
"type": "list",
"body": "Choose a department to connect with:",
"button_text": "View Departments",
"sections": [
{
"title": "Sales",
"rows": [
{"id": "new_quote", "title": "Get a Quote", "description": "Request pricing for our products"},
{"id": "enterprise", "title": "Enterprise Sales", "description": "For orders over 1000 units"}
]
},
{
"title": "Support",
"rows": [
{"id": "technical", "title": "Technical Support", "description": "Help with product issues"},
{"id": "billing", "title": "Billing Support", "description": "Invoice and payment questions"}
]
}
]
}'

Response​

{
"id": "msg_int_002",
"conversation_id": "conv_abc123",
"contact_id": "contact_xyz789",
"channel_id": "channel_wa_001",
"type": "interactive",
"interactive_type": "list",
"status": "sent",
"created_at": "2026-02-10T17:05:00Z"
}

Header Types​

The optional header object supports multiple formats:

Text header:

{"type": "text", "text": "Welcome"}

Image header:

{"type": "image", "url": "https://example.com/banner.jpg"}

Video header:

{"type": "video", "url": "https://example.com/demo.mp4"}

Document header:

{"type": "document", "url": "https://example.com/catalog.pdf", "filename": "catalog.pdf"}

Error Responses​

Most errors return detail as a message string. See Error Handling for the response shapes.

StatusdetailDescription
400"Channel type '<type>' does not support interactive messages."The channel does not support interactive messages
400"Duplicate button id '...'. ..."Two reply buttons share the same id
400"Contact does not have a WhatsApp ID or phone number"The contact can't be reached on WhatsApp
400{"error": "WHATSAPP_WINDOW_EXPIRED", "message": ...}WhatsApp: the 24-hour customer service window has closed. Send a template
400{"error": "WHATSAPP_NO_CUSTOMER_MESSAGE", "message": ...}WhatsApp: the contact has never written to you. Send a template
401"Invalid or expired API token"Token is invalid or expired
403"Missing required permission(s): messages:create"Token lacks the scope
404"Channel not found", "Contact not found"Unknown ID, or it belongs to another workspace
409{"error": "CHANNEL_DISCONNECTED", ...}The channel is disconnected
409{"error": "CONTACT_BLOCKED", ...}The contact is blocked
422list of field errorsInvalid request body, for example more than 3 buttons or an empty body

When the 24-hour window has closed, the request is refused with 400 WHATSAPP_WINDOW_EXPIRED before anything is sent (the same check as POST /messages). If WhatsApp rejects a message that was sent, the request still returns 201 with status: "failed", the reason in error and WhatsApp's numeric code in error_code (for example 131047), and the message.failed webhook fires once. Outside the window, send a template instead.

Next Steps​