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
| Scope | Purpose |
|---|---|
messages:create | Send interactive messages |
Channel Capabilities
Not all channels support all interactive features. Check before sending:
| Feature | Messenger | Telegram | SMS | Live Chat | |||
|---|---|---|---|---|---|---|---|
| Buttons | Yes (3 max) | Yes | Yes | Yes | No | No | Yes |
| List | Yes | No | No | No | No | No | Yes |
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
| Field | Type | Required | Description |
|---|---|---|---|
channel_id | string | Yes | The channel to send through |
contact_id | string | Yes | The recipient contact |
type | string | Yes | Must be buttons |
header | object | No | Optional header (text, image, video, or document) |
body | string | Yes | Main message text. Must contain at least one non-whitespace character |
footer | string | No | Footer text (smaller, muted) |
buttons | array | Yes | Array of button objects (max 3) |
Each button object:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique button identifier (returned when customer taps) |
title | string | Yes | Button 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.
List messages are currently supported on WhatsApp and Live Chat only.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
channel_id | string | Yes | The channel to send through |
contact_id | string | Yes | The recipient contact |
type | string | Yes | Must be list |
body | string | Yes | Main message text. Must contain at least one non-whitespace character |
button_text | string | Yes | Text on the button that opens the list |
sections | array | Yes | Array of section objects |
Each section object:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Section heading |
rows | array | Yes | Array of row items |
Each row object:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique row identifier |
title | string | Yes | Row title (max 24 characters) |
description | string | No | Row 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.
| Status | detail | Description |
|---|---|---|
| 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 |
| 422 | list of field errors | Invalid 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
- Carousel Messages -- multi-card scrollable carousels
- Reactions -- add emoji reactions to messages
- WhatsApp Interactive Messages -- WhatsApp-specific details