Create advanced chatbot replies with buttons, CTA links, and WhatsApp list menus.
Interactive Chatbot
Summary
Create advanced chatbot replies with buttons, CTA links, and WhatsApp list menus.
Prerequisites
- Authorization: Bearer w91_live_xxx
- Content-Type: application/json for JSON requests
Related documentation
Endpoint: POST /api/v2/chatbots/interactive. Use this route for WhatsApp interactive response types: buttons, cta, and list.
Buttons are limited to three choices, matching WhatsApp interactive button limits. CTA URLs must use HTTPS.
POST
/api/v2/chatbots/interactive| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | header | Required | Bearer w91_public_token_here. |
Content-Type | header | Required | application/json. |
senderId | string | Optional | WhatsApp sender number for global tokens. |
chatbot.name | string | Required | Name for the interactive chatbot. |
chatbot.trigger | object | Required | Trigger object with trigger.keyword or trigger.keywords. |
chatbot.response.type | string | Required | buttons, cta, or list. |
chatbot.response.text | string | Required | Main message body shown to the user. |
chatbot.response.footerText | string | Optional | Optional footer text for buttons and list responses. |
chatbot.response.buttons | array | Optional | Button rows for response.type=buttons. Each item needs id and label. |
chatbot.response.ctaText | string | Optional | Button label for response.type=cta. |
chatbot.response.ctaUrl | string | Optional | HTTPS destination URL for response.type=cta. |
chatbot.response.sections | array | Optional | List sections for response.type=list. Each section contains rows. |
chatbot.response.rows | array | Optional | Rows inside a list section. Each row needs id and title. |
Create button chatbot
curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"chatbot": {
"name": "Support Choices",
"trigger": { "keyword": "help" },
"response": {
"type": "buttons",
"text": "How can we help?",
"footerText": "Whats91",
"buttons": [
{ "id": "sales", "label": "Sales" },
{ "id": "support", "label": "Support" }
]
}
}
}'Interactive response
{
"success": true,
"message": "Chatbot created",
"data": {
"senderId": "916268662275",
"chatbot": {
"chatbotUid": "bot_support_choices",
"name": "Support Choices",
"botType": "advanced",
"replyTrigger": "help",
"replyText": "How can we help?",
"status": 1
}
},
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid"
}
}CTA Example
Open Portal CTA body
{
"senderId": "916268662275",
"chatbot": {
"name": "Open Portal",
"trigger": { "keyword": "portal" },
"response": {
"type": "cta",
"text": "Open your customer portal.",
"ctaText": "Open",
"ctaUrl": "https://app.example.com"
}
}
}List Example
Department Menu list body
{
"senderId": "916268662275",
"chatbot": {
"name": "Department Menu",
"trigger": { "keyword": "menu" },
"response": {
"type": "list",
"text": "Choose a department.",
"footerText": "Whats91",
"sections": [
{
"title": "Departments",
"rows": [
{ "id": "sales", "title": "Sales", "description": "Talk to sales" },
{ "id": "support", "title": "Support", "description": "Get product help" }
]
}
]
}
}
}Practical Interactive Examples
| Example | response.type | Trigger | Use case |
|---|---|---|---|
| Support Choices | buttons | help | Route users to Sales or Support quickly. |
| Open Portal | cta | portal | Send a single HTTPS portal link using ctaUrl. |
| Department Menu | list | menu | Show department sections and rows for routing. |
| Product Picker | list | products | Let users choose product categories from rows. |
| Payment Link | cta | pay | Open a secure hosted payment URL. |
| Store Locator | buttons | store | Offer city or region choices with three or fewer buttons. |
Validation Notes
- For buttons, every button requires id and label, and there can be no more than three buttons.
- For cta, ctaText and ctaUrl are required, and ctaUrl must be HTTPS.
- For list, sections must include rows, and each row must include id and title.
- Invalid button labels, missing list rows, or invalid CTA URLs return VALIDATION_FAILED.
SDK Examples
Use these examples as starting points for server-side implementations.
cURL
curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_live_xxx" \
-H "Content-Type: application/json" \
-d 'curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"chatbot": {
"name": "Support Choices",
"trigger": { "keyword": "help" },
"response": {
"type": "buttons",
"text": "How can we help?",
"footerText": "Whats91",
"buttons": [
{ "id": "sales", "label": "Sales" },
{ "id": "support", "label": "Support" }
]
}
}
}''Node.js
const response = await fetch("https://graph.whats91.com/api/v2/chatbots/interactive", {
method: "POST",
headers: {
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json"
},
body: JSON.stringify(curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"chatbot": {
"name": "Support Choices",
"trigger": { "keyword": "help" },
"response": {
"type": "buttons",
"text": "How can we help?",
"footerText": "Whats91",
"buttons": [
{ "id": "sales", "label": "Sales" },
{ "id": "support", "label": "Support" }
]
}
}
}')
});
const data = await response.json();
console.log(data);PHP
$ch = curl_init("https://graph.whats91.com/api/v2/chatbots/interactive");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer w91_live_xxx",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode(curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"chatbot": {
"name": "Support Choices",
"trigger": { "keyword": "help" },
"response": {
"type": "buttons",
"text": "How can we help?",
"footerText": "Whats91",
"buttons": [
{ "id": "sales", "label": "Sales" },
{ "id": "support", "label": "Support" }
]
}
}
}')
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Python
import requests
response = requests.request(
"POST",
"https://graph.whats91.com/api/v2/chatbots/interactive",
headers={
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json",
},
json=curl -X POST "https://graph.whats91.com/api/v2/chatbots/interactive" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"chatbot": {
"name": "Support Choices",
"trigger": { "keyword": "help" },
"response": {
"type": "buttons",
"text": "How can we help?",
"footerText": "Whats91",
"buttons": [
{ "id": "sales", "label": "Sales" },
{ "id": "support", "label": "Support" }
]
}
}
}'
)
print(response.json())C#
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer w91_live_xxx");
var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.whats91.com/api/v2/chatbots/interactive");
request.Content = new StringContent(
"""curl -X POST \"https://graph.whats91.com/api/v2/chatbots/interactive\" \
-H \"Authorization: Bearer w91_public_token_here\" \
-H \"Content-Type: application/json\" \
-d '{
\"senderId\": \"916268662275\",
\"chatbot\": {
\"name\": \"Support Choices\",
\"trigger\": { \"keyword\": \"help\" },
\"response\": {
\"type\": \"buttons\",
\"text\": \"How can we help?\",
\"footerText\": \"Whats91\",
\"buttons\": [
{ \"id\": \"sales\", \"label\": \"Sales\" },
{ \"id\": \"support\", \"label\": \"Support\" }
]
}
}
}'""",
Encoding.UTF8,
"application/json"
);
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());