Skip to main content

Send WhatsApp Interactive Message

Full reference for the endpoint that sends WhatsApp interactive messages — reply buttons, list pickers, and product messages.

Written by Tarek Khalil

Endpoint

POST https://app.octopods.io/api/v1/whatsapp/interactive

Interactive messages do not require template approval, but WhatsApp only allows them inside the 24-hour messaging window that opens after a customer’s most recent inbound message. Outside that window you must send an approved template instead. See Send WhatsApp Template Message.

Authentication

Include your WhatsApp Business API Key in the request header:

X-Octopods-Auth: YOUR_WHATSAPP_BUSINESS_API_KEY

Required parameters

Send the request body as JSON with Content-Type: application/json.

  • destination_phone — the recipient’s phone number in E.164 format. Must belong to a customer with an open 24-hour window.

  • waba_interactive_message — the interactive payload itself (see “Message structure” below). May be sent as an object or as a stringified JSON value.

Optional parameters

  • intercom_teammate_id — the ID of the Intercom teammate who should appear as the sender. Defaults to the workspace’s configured default sender.

Message structure

The waba_interactive_message object always contains:

  • type — one of button, list, product, product_list, flow, catalog_message. The last two are only supported on WhatsApp Cloud channels.

  • body — the main message text shown to the recipient. Must contain a non-empty text field.

  • action — type-specific payload defining the buttons, list rows, or product(s). Required for every type.

  • header (optional) — a header above the body. Can be a text header or a media header (image, video, document). Required for product_list; not allowed for product or catalog_message.

  • footer (optional) — a short line of text below the interactive element. Must contain a non-empty text field if provided.

Reply buttons (type: "button")

Up to three tappable buttons that send a pre-filled reply back when the recipient taps one.

{
  "destination_phone": "+15551234567",
  "waba_interactive_message": {
    "type": "button",
    "body": { "text": "Did your order arrive today?" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "yes_delivered", "title": "Yes, received" } },
        { "type": "reply", "reply": { "id": "no_missing",    "title": "Not yet" } },
        { "type": "reply", "reply": { "id": "issue",         "title": "There's a problem" } }
      ]
    }
  }
}

List picker (type: "list")

A tappable menu that opens a scrollable list of options, grouped into sections.

{
  "destination_phone": "+15551234567",
  "waba_interactive_message": {
    "type": "list",
    "body": { "text": "Which topic would you like help with today?" },
    "action": {
      "button": "Pick a topic",
      "sections": [
        {
          "title": "Orders",
          "rows": [
            { "id": "track",  "title": "Track my order" },
            { "id": "return", "title": "Return an item" }
          ]
        },
        {
          "title": "Account",
          "rows": [
            { "id": "password", "title": "Reset password" },
            { "id": "billing",  "title": "Billing question" }
          ]
        }
      ]
    }
  }
}

Media header

Attach an image, video, or document above the body by setting header:

"header": {
  "type": "image",
  "image": { "link": "https://example.com/invoice-preview.png" }
}

Accepted header types are text, image, video, and document. Media headers require a valid, publicly reachable URL under the matching key (image.link, video.link, or document.link).

Example request

POST https://app.octopods.io/api/v1/whatsapp/interactive
X-Octopods-Auth: YOUR_WHATSAPP_BUSINESS_API_KEY
Content-Type: application/json{
  "destination_phone": "+15551234567",
  "waba_interactive_message": {
    "type": "button",
    "body": { "text": "Ready to confirm your appointment?" },
    "footer": { "text": "You can reschedule any time." },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "confirm",    "title": "Confirm" } },
        { "type": "reply", "reply": { "id": "reschedule", "title": "Reschedule" } }
      ]
    }
  }
}

Success response

On success the API returns HTTP 201 Created:

{
  "request_id": "3e6b1d2a-9f4e-4c1d-8b7a-1b3c5d7e9f0a",
  "message_id": 3851834,
  "channel_message_id": "wamid.HBgNNTU..."
}

Use message_id with the status endpoint to track delivery.

Error response

{
  "request_id": "3e6b1d2a-9f4e-4c1d-8b7a-1b3c5d7e9f0a",
  "error_code": 2,
  "error": "You must supply WhatsApp Interactive Type as one of the valid types button, list, product, product_list. Provided type: dropdown."
}

Error codes

Code

Name

When it happens

1

ARGUMENT_MISSING

destination_phone or waba_interactive_message is missing, or a required field inside the payload is absent (body text, action, header for product_list).

2

TYPE_MISMATCH

type is not one of the allowed values, or a field has the wrong shape.

5

PHONE_INVALID

destination_phone failed E.164 validation.

6

DEPRECATED_API_KEY

The API key has been rotated or revoked.

7

WHATSAPP_ERROR

WhatsApp rejected the send (for example, the 24-hour window has closed).

8

INVALID_HEADER

The header is missing a required field, has media attached where media is not allowed, or the media URL is invalid.

Handling replies

When a customer taps a reply button or list option:

  1. WhatsApp sends an inbound message to Octopods with the selected option’s id and title.

  2. Octopods appends it to the same conversation in your Intercom or HubSpot inbox.

  3. Your automation or an agent handles the response like any other inbound WhatsApp message.

Rate limits

Interactive sends share the same per-API-key rate limit as WhatsApp template sends. On a breach, the response is HTTP 429 with a retry timestamp; pause sends until the timestamp passes before retrying.


What’s next

Did this answer your question?