WhatsAble
API Documentation

Button replies

Send WhatsApp reply buttons and know which button a customer tapped: the button_reply field on your webhook, on n8n, Make and Zapier triggers, and on the Public API v1 Message.

When a customer taps a button in WhatsApp, WhatsAble records which option they tapped and which message offered it. Your webhook, your n8n, Make or Zapier trigger, and the Public API v1 all receive the same button_reply object. Your automation can then branch on the button's id, not on its label.

What you can do with it

  • Confirm or cancel an appointment. Send "Confirm" and "Reschedule" buttons. Route each tap to the correct step in your booking tool.
  • Qualify a lead. Ask "Which plan interests you?" with three buttons. Write the chosen id to your CRM.
  • Collect a survey answer. Send a rating question. Store the id of each answer with the message that asked it.
  • Translate your buttons safely. The id stays the same in every language, so your automation does not break when you change a label.
  • Know which message the customer answered. When you send the same question two times, message_id tells you which one the customer tapped.

How it works

  1. You send a message with reply buttons. Each button has your own id and a title (the label the customer sees).
  2. The customer taps one button. WhatsApp sends the tap to WhatsAble as an incoming message.
  3. WhatsAble stores the tap with the option's id and a link to the message that offered the buttons.
  4. Your webhook or trigger receives the incoming message with a button_reply object. The Public API v1 returns the same object on that message.
  5. In the WhatsAble inbox, the tap shows the caption Chose an option, with a quote of the message that offered the buttons.

A tap on a template's quick-reply button works the same way. Its id is the button payload that you set on the template.

The AI agent reads a tap as the customer's text, which is the button's title. The option id does not change what the AI agent sees.

Send reply buttons with the Public API v1

Send POST https://api.whatsable.app/v1/messages with type: "buttons". Authenticate with an API key from Settings → API (Authorization: Bearer nfy_live_...).

{
  "to": "+5491155550000",
  "type": "buttons",
  "buttons": {
    "body": "Your appointment is tomorrow at 10:00. Can you come?",
    "options": [
      { "id": "appt_8812_confirm", "title": "Confirm" },
      { "id": "appt_8812_reschedule", "title": "Reschedule" }
    ]
  }
}
buttons.bodystringrequired

The text above the buttons, up to 1,024 characters.

buttons.optionsarrayrequired

One to three buttons. Ids and titles must not repeat.

Show Option properties
idstringrequired

Your id for the button, up to 256 characters, with no space at the start or the end. The tap returns it as button_reply.id. Put the information your automation needs in it, for example a booking number.

titlestringrequired

The button label that the customer sees, up to 20 characters.

WhatsApp accepts reply buttons only inside the 24-hour customer service window. Outside the window the API answers 422 session_window_closed. To start a conversation, send a template with quick-reply buttons.

The button_reply object

button_replyobject

The option the customer tapped.

Show Properties
idstring | null

The id of the tapped option: the id you gave a reply button, or the payload of a template quick-reply button. It is exactly as WhatsApp sent it. Null when WhatsApp sent no id.

titlestring

The label of the tapped option. It is the same as the message text.

message_idstring | null

The WhatsAble id of the message that offered the option. It is the same id as the id of that message in the Public API v1. Null when WhatsAble did not store that message in this conversation.

whatsapp_message_idstring | null

The WhatsApp message id (wamid) of the message that offered the option. Null when WhatsApp did not name the message.

On your webhook, n8n, Make and Zapier

The incoming message payload gets a top-level button_reply key. It comes after all the other keys, and only on a tap. A payload for any other message does not change.

  • message_type is interactive for a tap on a reply button, and button for a tap on a template's quick-reply button.
  • last_message_of_user is the button's title, as before.
{
  "last_messages": "[...]",
  "conversation_paragraph": "Bot (09:58:02 AM): Your appointment is tomorrow at 10:00. Can you come? ; User (10:02:11 AM): Confirm",
  "phone_number": 5491155550000,
  "recipient_name": "Ana Lopez",
  "user_id": "158c59e1-ea85-4d0b-b70c-65328ba67a8e",
  "last_message_of_user": "Confirm",
  "last_message_of_bot": "Your appointment is tomorrow at 10:00. Can you come?",
  "message_type": "interactive",
  "user_last_message_time": 1793102531000,
  "bot_last_message_time": 1793102282000,
  "attachment_url": null,
  "note": "",
  "note_automation": "",
  "labels": "",
  "incoming_message": true,
  "is_scheduled": false,
  "button_reply": {
    "id": "appt_8812_confirm",
    "title": "Confirm",
    "message_id": "cm2v8m1a00001qz8h0p1q2r3s",
    "whatsapp_message_id": "wamid.HBgMNTQ5MTE1NTU1MDAwMBUCABEYEjQ"
  }
}

The full payload reference is on Message webhooks.

On the Public API v1 Message

Every Message resource has a button_reply field. GET /v1/messages and GET /v1/messages/{id} return it.

  • On a tap, type is interactive_reply for a reply button and button_reply for a template quick-reply button. button_reply holds the object above.
  • On every other message, button_reply is null.
{
  "object": "message",
  "id": "cm2v8m9z00004qz8hq7r8s9t0",
  "direction": "inbound",
  "type": "interactive_reply",
  "text": "Confirm",
  "button_reply": {
    "id": "appt_8812_confirm",
    "title": "Confirm",
    "message_id": "cm2v8m1a00001qz8h0p1q2r3s",
    "whatsapp_message_id": "wamid.HBgMNTQ5MTE1NTU1MDAwMBUCABEYEjQ"
  }
}

The example shows only the fields that matter here. The full schema is at https://api.whatsable.app/v1/openapi.json.

Taps from before this field existed

WhatsAble started to record the option id on 2026-10-27. On an older tap, button_reply.id and button_reply.whatsapp_message_id are null. title still holds the label. To match an older tap, compare its title with the button labels, which are unique within one message.

On this page