Table of Contents
< All Topics

Complete Guide to Interactive Messages

Introduction to Interactive Messages

Interactive messages allow you to create rich, engaging conversations with your customers by providing structured choices through list menus or reply buttons. Instead of free-form text responses, customers can simply tap to select their choice, making conversations more efficient and reducing friction.

This guide covers the two types of interactive messages supported by the Coext External API:

  • Interactive List Messages: Display a menu button that opens a list of options organized in sections
  • Interactive Button Messages: Display 1-3 clickable reply buttons directly in the message

When to Use Interactive Messages

Use CaseRecommended TypeWhy
Product catalog browsingList MessageCan show many options organized by category
Appointment slot selectionList MessageDisplay time slots grouped by day
Order confirmation (Yes/No)Button MessageSimple binary choice, always visible
Rating feedback (1-3)Button MessageUp to 3 quick options
Main menu navigationList MessageMany options, clean presentation

โœ… Permission Required: Interactive messages require the send_text permission on your API key. Ensure this permission is enabled in your API key configuration.

Interactive List Messages

List messages display a button that, when tapped, opens a menu of options organized into sections. This is ideal when you have multiple choices that don’t fit comfortably as buttons.

List Message Structure

  • Header (optional): Text displayed at the top of the message
  • Body (required): Main message text explaining what to do
  • Footer (optional): Small text at the bottom
  • Button (required): Text on the button that opens the list
  • Sections (required): Groups of selectable options

API Endpoint

POST /api/v1/external/messages/interactive/list
            

Request Body Schema

FieldTypeRequiredLimitsDescription
tostringYesE.164 formatRecipient’s phone number
headerstringNoMax 60 charsHeader text at the top
bodystringYesMax 1024 charsMain message text
footerstringNoMax 60 charsFooter text at the bottom
buttonstringYesMax 20 charsText on the menu button
sectionsarrayYes1-10 sectionsArray of section objects
referencestringNoMax 100 charsYour tracking reference

Section Object Schema

titleOptional, max 24 characters
rowsRequired, array of 1-10 row objects

Row Object Schema

idRequired, max 200 chars, unique identifier
titleRequired, max 24 characters
descriptionOptional, max 72 characters

Example 1: Product Catalog

Display a product catalog with categories:

curl -X POST "https://your-domain.com/api/v1/external/messages/interactive/list" 
  -H "Content-Type: application/json" 
  -H "X-API-Key: pk_live_your_api_key_here" 
  -d '{
    "to": "+919876543210",
    "header": "๐Ÿ›๏ธ Our Products",
    "body": "Browse our popular products and select one to learn more!",
    "footer": "Tap View Catalog to see options",
    "button": "View Catalog",
    "sections": [
      {
        "title": "Electronics",
        "rows": [
          {
            "id": "prod_laptop_001",
            "title": "Laptop Pro 15",
            "description": "High-performance laptop - $999"
          },
          {
            "id": "prod_phone_001",
            "title": "SmartPhone X",
            "description": "Latest flagship phone - $799"
          }
        ]
      },
      {
        "title": "Accessories",
        "rows": [
          {
            "id": "prod_headphones_001",
            "title": "Wireless Headphones",
            "description": "Noise-canceling - $299"
          }
        ]
      }
    ],
    "reference": "catalog-browse-001"
  }'
            

Example 2: Appointment Scheduling

Let customers select an appointment slot:

curl -X POST "https://your-domain.com/api/v1/external/messages/interactive/list" 
  -H "Content-Type: application/json" 
  -H "X-API-Key: pk_live_your_api_key_here" 
  -d '{
    "to": "+919876543210",
    "header": "๐Ÿ“… Book Appointment",
    "body": "Please select your preferred time slot for the consultation.",
    "footer": "All times in IST",
    "button": "Select Time",
    "sections": [
      {
        "title": "Monday, Dec 25",
        "rows": [
          { "id": "slot_mon_10", "title": "10:00 AM", "description": "1 hour session" },
          { "id": "slot_mon_14", "title": "2:00 PM", "description": "1 hour session" }
        ]
      },
      {
        "title": "Tuesday, Dec 26",
        "rows": [
          { "id": "slot_tue_09", "title": "9:00 AM", "description": "1 hour session" },
          { "id": "slot_tue_11", "title": "11:00 AM", "description": "1 hour session" }
        ]
      }
    ],
    "reference": "booking-123"
  }'
            

JavaScript (Node.js) Example

const API_KEY = process.env.COEXT_API_KEY;
const BASE_URL = 'https://your-domain.com/api/v1/external';

async function sendListMessage(to, body, button, sections, options = {}) {
  const response = await fetch(`${BASE_URL}/messages/interactive/list`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify({
      to,
      body,
      button,
      sections,
      header: options.header,
      footer: options.footer,
      reference: options.reference
    })
  });
  
  return response.json();
}

// Usage - Support Menu
const result = await sendListMessage(
  '+919876543210',
  'How can we help you today?',
  'Get Help',
  [
    {
      title: 'Orders',
      rows: [
        { id: 'track_order', title: 'Track My Order', description: 'Check order status' },
        { id: 'return_order', title: 'Return/Exchange', description: 'Start a return' }
      ]
    },
    {
      title: 'Support',
      rows: [
        { id: 'talk_agent', title: 'Talk to Agent', description: 'Live chat support' }
      ]
    }
  ],
  { reference: 'support-menu-001' }
);

console.log('Message ID:', result.data.message_id);
            

Interactive Button Messages

Button messages display 1-3 reply buttons directly in the message, making them immediately visible and tappable without opening a menu.

Button Message Structure

  • Header (optional): Can be text, image, video, or document
  • Body (required): Main message text
  • Footer (optional): Small text at the bottom
  • Buttons (required): 1-3 reply buttons

API Endpoint

POST /api/v1/external/messages/interactive/button
            

Request Body Schema

FieldTypeRequiredDescription
tostringYesRecipient phone number (E.164)
headerobjectNoHeader with type and content
bodystringYesMessage text (max 1024 chars)
footerstringNoFooter text (max 60 chars)
buttonsarrayYesArray of 1-3 button objects
referencestringNoYour tracking reference

Header Object Types

Text Header{ "type": "text", "text": "Your Header" }
Image Header{ "type": "image", "image": { "link": "https://..." } }
Video Header{ "type": "video", "video": { "link": "https://..." } }
Document Header{ "type": "document", "document": { "link": "https://...", "filename": "file.pdf" } }

Button Object Schema

idRequired, max 256 chars, unique identifier
titleRequired, max 20 characters

Example 1: Order Confirmation

Ask for order confirmation with a simple Yes/No:

curl -X POST "https://your-domain.com/api/v1/external/messages/interactive/button" 
  -H "Content-Type: application/json" 
  -H "X-API-Key: pk_live_your_api_key_here" 
  -d '{
    "to": "+919876543210",
    "body": "Your order #12345 is ready to be shipped!nnTotal: $99.99nDelivery: Standard (3-5 days)nnWould you like to confirm?",
    "footer": "Reply within 24 hours",
    "buttons": [
      { "id": "confirm_order_12345", "title": "โœ… Confirm" },
      { "id": "cancel_order_12345", "title": "โŒ Cancel" }
    ],
    "reference": "order-confirm-12345"
  }'
            

Example 2: With Text Header

curl -X POST "https://your-domain.com/api/v1/external/messages/interactive/button" 
  -H "Content-Type: application/json" 
  -H "X-API-Key: pk_live_your_api_key_here" 
  -d '{
    "to": "+919876543210",
    "header": {
      "type": "text",
      "text": "๐ŸŽ‰ Special Offer!"
    },
    "body": "Get 20% off your next purchase with code SAVE20.nnValid until December 31, 2025.",
    "footer": "Terms and conditions apply",
    "buttons": [
      { "id": "shop_now", "title": "Shop Now" },
      { "id": "save_later", "title": "Save for Later" },
      { "id": "no_thanks", "title": "No Thanks" }
    ]
  }'
            

Example 3: With Image Header

curl -X POST "https://your-domain.com/api/v1/external/messages/interactive/button" 
  -H "Content-Type: application/json" 
  -H "X-API-Key: pk_live_your_api_key_here" 
  -d '{
    "to": "+919876543210",
    "header": {
      "type": "image",
      "image": {
        "link": "https://example.com/products/laptop-pro-15.jpg"
      }
    },
    "body": "Laptop Pro 15 is back in stock!nn๐Ÿ’ป 15-inch Retina Displaynโšก M3 Pro Chipn๐Ÿ’พ 16GB RAMnnPrice: $999",
    "buttons": [
      { "id": "buy_laptop_001", "title": "Buy Now" },
      { "id": "details_laptop_001", "title": "View Details" }
    ],
    "reference": "restock-notify-laptop"
  }'
            

JavaScript (Node.js) Example

const API_KEY = process.env.COEXT_API_KEY;
const BASE_URL = 'https://your-domain.com/api/v1/external';

async function sendButtonMessage(to, body, buttons, options = {}) {
  const response = await fetch(`${BASE_URL}/messages/interactive/button`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify({
      to,
      body,
      buttons,
      header: options.header,
      footer: options.footer,
      reference: options.reference
    })
  });
  
  return response.json();
}

// Usage - Customer Satisfaction Survey
const result = await sendButtonMessage(
  '+919876543210',
  'Thank you for your purchase! How was your experience?',
  [
    { id: 'rating_great', title: '๐Ÿ˜ Great!' },
    { id: 'rating_okay', title: '๐Ÿ˜ Okay' },
    { id: 'rating_poor', title: '๐Ÿ˜ž Poor' }
  ],
  { 
    footer: 'Your feedback helps us improve',
    reference: 'survey-456'
  }
);

console.log('Message ID:', result.data.message_id);
            

Python Example

import os
import requests

API_KEY = os.environ.get('COEXT_API_KEY')
BASE_URL = 'https://your-domain.com/api/v1/external'

def send_button_message(to: str, body: str, buttons: list, **options) -> dict:
    headers = {
        'Content-Type': 'application/json',
        'X-API-Key': API_KEY
    }
    
    payload = {
        'to': to,
        'body': body,
        'buttons': buttons,
        **{k: v for k, v in options.items() if v is not None}
    }
    
    response = requests.post(
        f'{BASE_URL}/messages/interactive/button',
        json=payload,
        headers=headers
    )
    
    return response.json()

# Usage - Order Confirmation
result = send_button_message(
    '+919876543210',
    'Your order is ready. Confirm shipment?',
    [
        {'id': 'confirm', 'title': 'Confirm'},
        {'id': 'modify', 'title': 'Modify Order'}
    ],
    reference='order-789'
)

print(f"Message ID: {result['data']['message_id']}")
            

Handling Responses

Success Response

{
  "success": true,
  "data": {
    "message_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "sent"
  },
  "meta": {
    "request_id": "req_abc123def456",
    "rate_limit": {
      "limit": 60,
      "remaining": 58,
      "reset_at": "2025-12-23T14:30:00.000Z"
    }
  }
}
            

Error Response

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "buttons must have at most 3 items"
  },
  "meta": {
    "request_id": "req_xyz789"
  }
}
            

Common Error Codes

CodeHTTPDescription
VALIDATION_ERROR400Request body validation failed
PERMISSION_DENIED403API key lacks send_text permission
INVALID_API_KEY401API key not found or invalid
RATE_LIMIT_EXCEEDED429Too many requests
MESSAGE_SEND_FAILED500WhatsApp API error

Receiving User Replies via Webhooks

When a customer taps a button or selects a list item, their response is sent to your webhook. Configure webhooks in your API key settings.

Button Reply Webhook

{
  "event": "message.received",
  "timestamp": "2025-12-23T14:35:00.000Z",
  "data": {
    "message_id": "wamid.xyz123",
    "from": "+919876543210",
    "to": "+14155551234",
    "message": {
      "type": "button",
      "button": {
        "text": "Confirm",
        "payload": "confirm_order_12345"
      }
    }
  }
}
            

List Reply Webhook

{
  "event": "message.received",
  "timestamp": "2025-12-23T14:35:00.000Z",
  "data": {
    "message_id": "wamid.abc456",
    "from": "+919876543210",
    "to": "+14155551234",
    "message": {
      "type": "interactive",
      "interactive": {
        "type": "list_reply",
        "list_reply": {
          "id": "prod_laptop_001",
          "title": "Laptop Pro 15"
        }
      }
    }
  }
}
            

Best Practices

Design Guidelines

  1. Keep titles short: Buttons have 20-char limit, list items have 24-char limit
  2. Use unique IDs: Always use descriptive, unique IDs for tracking responses
  3. Add context in body: Explain what each option does before the choices
  4. Use emojis sparingly: They can help differentiate options but don’t overuse
  5. Include clear call-to-action: Tell users what action you expect

๐Ÿ’ก Tip: Use Button Messages for 1-3 simple choices that should be immediately visible. Use List Messages for 4+ options or when you need to organize choices into categories.

Technical Recommendations

  • Store the message_id: You’ll need it to correlate with webhook responses
  • Use the reference field: Include your internal order/transaction ID
  • Handle rate limits: Implement exponential backoff on 429 errors
  • Validate before sending: Check character limits client-side to avoid errors
  • Set up webhooks: Essential for receiving user responses

Quick Reference: Character Limits

List Message Limits

ElementLimit
Header text60 characters
Body text1,024 characters
Footer text60 characters
Button text20 characters
Sections1-10 sections
Rows per section1-10 rows
Row ID200 characters
Row title24 characters
Row description72 characters

Button Message Limits

ElementLimit
Header text60 characters
Body text1,024 characters
Footer text60 characters
Number of buttons1-3 buttons
Button ID256 characters
Button title20 characters

Leave a Reply

Your email address will not be published. Required fields are marked *