GLOSSARY

What is an Interactive Message?

An interactive message is a WhatsApp message with type "interactive", which renders tappable UI inside the chat instead of plain text: reply buttons, a list menu, a call-to-action URL button, a product card or a Flow. Sent free-form it needs no template approval, but it can only go out while the 24-hour customer service window is open.

Free forever plan · No credit card required · Cancel anytime

Quick definition

An interactive message is a WhatsApp message with type "interactive", which renders tappable UI inside the chat instead of plain text: reply buttons, a list menu, a call-to-action URL button, a product card or a Flow. Sent free-form it needs no template approval, but it can only go out while the 24-hour customer service window is open.

In a single sentence: a tap instead of a typo, and a structured id instead of a guess at what the customer meant.

What it means

An interactive message is what happens when you stop asking customers to type. Instead of "reply 1 for delivery, 2 for returns", you send buttons. Instead of listing twelve branch names in a paragraph, you send a menu. The message body is still text, but the answer comes back as a structured payload with an identifier you chose.

On the wire it is a message with type: "interactive" and an interactive object whose own type selects the widget: reply buttons, a list menu, a call-to-action URL button, a Flow, or a product card. Each has its own body shape and its own limits.

The reason this matters more on WhatsApp than on other channels is the parsing problem it removes. Free-text answers on a messaging channel arrive misspelled, in mixed languages, with emoji, and with the answer to a different question. A tapped button arrives as an id you defined, every time, in every language, with no natural language processing in between.

The window rule, and why it is good news

Free-form interactive messages can only be sent while the 24-hour customer service window is open. Outside it, you are back to approved templates, which can carry quick-reply and URL buttons of their own but need review before every change.

Read that as an opportunity rather than a restriction. Everything inside the window is deployable without a reviewer. You can ship a new menu, restructure a support triage flow, add a fourth option and remove it again, all on your own release schedule. The approval queue only constrains the small set of messages that have to start conversations from cold.

So the healthy architecture is thin at the boundary and rich inside it: a small, stable library of templates whose job is to earn a tap, and a large, fast-moving set of interactive experiences that live in the conversation the tap opened.

The payload shape that catches everyone

Here is the bug we see in almost every first integration. A tap on a reply button in a free-form interactive message and a tap on a quick-reply button in a template produce two different inbound structures.

The interactive one arrives as type: "interactive" with interactive.type set to button_reply, carrying your id and the title the customer saw. The template one arrives as type: "button" with a button object carrying payload and text. A list selection is a third shape, interactive.type of list_reply, which also includes the row description.

A handler written against only the first shape looks correct in testing, because testing happens inside an open window, and then silently drops every response to a template button in production. The symptom is maddening: customers insist they answered, and your system has no record of it. Write one normaliser that maps all three shapes onto a single internal event and the whole class of bug disappears.

Design rules that survive contact with real users

  • Ids are intents, titles are copy. Switch on id, never on the visible label. Labels get reworded and translated; ids should not.
  • Three buttons is a feature. The cap forces the question "what are the three things this person is actually trying to do", which is a better product question than any menu structure.
  • Always accept typing. A menu is a suggestion, not a constraint. People will reply "2" or "the first one" or write a sentence, and answering that with "please use the buttons" is how a block is earned.
  • Do not rebuild a phone tree. Four levels of nested menu is worse than a human, and people abandon it. Two levels then a person is a good default.
  • Use cta_url for links. A raw payment URL in text looks like phishing. A button with a clear label does not.
  • Include an escape hatch. One option should always be "talk to someone", and it should work.

Why it matters

The commercial case is conversion and cost at once. A tap is faster than typing, so completion rates on a structured question are far higher than on the same question asked in prose. A tap is unambiguous, so automation resolves more conversations without a human. And a tap is an inbound message, so it keeps the service window open, which keeps the rest of the conversation free-form and cheap.

That last point deserves emphasis because it links directly to your bill. Every button you put on a notification template is an invitation to re-open the window. A confirmed appointment that comes back as a tap has both captured the answer and bought you another 24 hours of unrestricted conversation.

Real-world examples

  1. Appointment confirmation. A utility template with "Confirm" and "Reschedule". Confirm writes to the calendar and ends the thread. Reschedule opens the window and the bot sends a list of available slots as a free-form list message, with no approval needed to change the slots.
  2. Support triage. Three buttons on first contact: order status, returns, something else. The first two are resolved by automation; the third routes straight to a human with the transcript attached.
  3. Payment link. A short body plus a cta_url button labelled "Pay securely". The link is never visible as raw text, which removes the phishing look and measurably improves click-through.
  4. Branch selection. Twelve locations across three regions, sent as a list grouped into sections. A paragraph listing twelve branch names would have been ignored.
  5. The escalation that worked. Every menu carried a "talk to a person" row. Usage was low, satisfaction was high, and the option itself was what stopped people abandoning the menu.

Common mistakes

  • Handling only one reply shape. Template buttons and interactive buttons are different payloads. Handle both.
  • Switching on the title. The first translation or rewrite breaks every branch of your logic.
  • Reusing ids across contexts. A generic "option_1" tells you nothing when it arrives out of context.
  • Sending a list where three buttons would do. A list costs an extra tap to open. Use it when there are genuinely more than three options.
  • Assuming a tap is guaranteed. People type. Plan for it.
  • Forgetting the window. A free-form interactive send after the window closes fails, exactly like any other free-form message.

Related concepts

How Pinlyx handles it

Pinlyx normalises all three reply shapes into one event, so a tap on a template button and a tap on an interactive button reach your automation identically and nothing is silently lost. Menus are built visually with the current limits enforced before send, button ids are treated as stable intents that survive translation, and every tap is written to the contact timeline as a recorded answer rather than as an inbound text to be parsed later. Free text always reaches a human when it does not match, and the same builder produces Telegram and Instagram equivalents from one definition. See WhatsApp CRM.

Decision table · which interactive type

Five widgets, and the question each one answers.

Exact character counts and availability move, so validate against Meta's current documented limits.

interactive.typeRenders asBest forLimits
buttonUp to three reply buttons under the message body.A short, closed choice: confirm or reschedule, yes or no, pick one of three departments.Three buttons maximum, and button titles are very short. Titles must be unique within the message.
listA "menu" button that opens a scrollable list, grouped into sections with a title and optional description per row.More options than buttons allow: branch selection, service catalogue, appointment slots.Ten rows in total across all sections, and each row needs a unique id. Row titles and descriptions are short.
cta_urlA single button that opens a URL, with the link not shown as raw text.Sending someone to a payment page or a tracking page without pasting an ugly link.One URL per message. The tap leaves WhatsApp, so nothing comes back to your webhook.
flowA button that opens a multi-screen form inside WhatsApp.Structured data collection: booking, onboarding, a returns request, a survey.Needs a published Flow. The completed submission returns as an nfm_reply payload.
product / product_listA product card or a multi-product catalogue message.Commerce accounts with a synced Meta catalogue.Requires a catalogue connected to the business, and availability varies by market.
Send, then read the tap

Three reply shapes, one normaliser.

Copy the normaliser. It is the difference between a working bot and a bot that loses half its answers.

# Outbound: three reply buttons, free-form, window must be open
POST /v22.0/{phone-number-id}/messages
{
  "messaging_product": "whatsapp",
  "to": "905551112233",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": { "text": "How can we help with order AC-10432?" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "track_order",  "title": "Where is it?" } },
        { "type": "reply", "reply": { "id": "start_return", "title": "Return it" } },
        { "type": "reply", "reply": { "id": "talk_human",   "title": "Talk to us" } }
      ]
    }
  }
}

# Inbound A: tap on the interactive button above
{ "type": "interactive",
  "interactive": { "type": "button_reply",
    "button_reply": { "id": "track_order", "title": "Where is it?" } } }

# Inbound B: tap on a QUICK REPLY button of a TEMPLATE. Different shape.
{ "type": "button",
  "button": { "payload": "track_order", "text": "Where is it?" } }

# Inbound C: selection from a list message
{ "type": "interactive",
  "interactive": { "type": "list_reply",
    "list_reply": { "id": "branch_kadikoy", "title": "Kadikoy",
                    "description": "Open until 20:00" } } }

// One normaliser for all three, plus the text people type anyway
function intentOf(msg) {
  if (msg.type === 'button') return msg.button.payload;
  if (msg.type === 'interactive') {
    const i = msg.interactive;
    if (i.type === 'button_reply') return i.button_reply.id;
    if (i.type === 'list_reply')   return i.list_reply.id;
    if (i.type === 'nfm_reply')    return 'flow_completed';
  }
  if (msg.type === 'text') return matchLooseIntent(msg.text.body); // may be null
  return null;
}
Build checklist

Six rules for menus people actually use.

  • Normalise button_reply, list_reply and template button payloads into one internal event.
  • Branch on ids, never on visible titles, so translations cannot break your logic.
  • Keep it to three buttons unless there are genuinely more than three answers.
  • Always accept free text as an answer to the same question.
  • Put a "talk to a person" option in every menu, and make it reach a person.
  • Never nest more than two levels of menu before a human is offered.
Watch out for

The half of your answers you never see.

Everything works in testing, because testing happens inside an open window with free-form interactive messages. Then production sends templates, customers tap the quick-reply buttons on those templates, and the payloads arrive in a shape your handler does not recognise. Nothing errors. The events are simply dropped, customers swear they replied, and the logs agree with them. One normaliser, written on day one, is all it takes to avoid it.

Interactive messages: FAQ

What teams ask when they move from plain text to taps.

Not when they are sent free-form. Inside an open 24-hour customer service window an interactive message is an ordinary message, so you can ship a new button menu in an afternoon with no review queue. Approval only enters the picture when you want buttons on a template, which is what you need to start a conversation from outside the window. That asymmetry is worth designing around: put your experimentation inside the window and keep the template set small and stable.
From the inbound webhook, but the shape depends on where the button came from, and this is the single most common integration bug on this feature. A reply button on a free-form interactive message returns type "interactive" with interactive.type of button_reply and an object holding your id and the title. A quick-reply button on a template returns type "button" with a button object holding payload and text. Two different structures for what looks like the same tap, so handle both or you will silently drop half your responses.
Because the id is the only stable thing in the payload. Titles are what the customer sees, they get reworded, translated and shortened, and any handler that switches on the title breaks the moment a copywriter improves it. Set ids that read like intents rather than labels, keep them stable across languages, and treat them as an API contract between your message and your handler.
Reply buttons cap at three, which is a design constraint rather than an inconvenience: three is roughly the number of options a person will read on a phone. Lists allow more, capped at ten rows in total across all sections, with short titles and optional short descriptions. Meta publishes the exact character counts and adjusts them, so validate against the current documented limits and fail loudly in your own code rather than discovering a truncated label in production.
You get an ordinary text message, and your handler has to cope. People reply "1", or "the first one", or a sentence that answers a question you did not ask. A menu is not a state machine that forces compliance, and any bot that answers a free-text reply with "please choose an option" earns its blocks. Match the obvious cases, hand ambiguous ones to a human, and keep the menu available rather than repeating it.
Not free-form. Outside the window your only option is an approved template, and templates can carry their own quick-reply and URL buttons, which is how you get an interactive first touch. The pattern that works is a template with buttons to open the conversation, then rich free-form interactive messages once the customer taps and the window opens. The tap is doing double duty: it captures intent and it makes everything that follows cheaper and more flexible.
Ready to ship

Let customers tap. Stop parsing.

Pinlyx builds WhatsApp buttons, lists and Flows visually, and normalises every reply shape into one event your automation can trust.

Free forever plan · GDPR-ready · No credit card required

We value your privacy

We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.