Pick the right interactive type
All of them need
text — the message body above the buttons or the list button. They are mutually exclusive: one interactive type per message. (buttons can also ride on a template send; list, carousel and flow cannot.)
Send a list
202 with id and correlationId. Keep the id: it is how you tie the customer’s choice back to this menu (see Match the choice below).
header and buttons are not allowed together with list.
Send reply buttons
reply, buttons can be url, call or copy — the full shapes are in Send interactive.
Receive the customer’s choice
The choice arrives on your webhook like any other inbound message. What the payload looks like depends on how the number is connected — the same rule as every other inbound event (Which events your number sends).- Meta Cloud API (official)
- Unofficial (Pilot Status web)
You receive Meta’s native envelope (webhook field A reply button arrives the same way with
messages), with type: "interactive". The id you set on the row or button comes back, and context.id is the wamid of the message that carried the menu."type": "button_reply" and "button_reply": { "id": "pay-slip:inv-2041", "title": "Bank slip" }.Branch on interactive.list_reply.id / interactive.button_reply.id — that is your ERP key, untouched.Match the choice to the menu
Your bot usually has several menus open with different customers. To know which menu a choice belongs to, keep a small record per sent menu:POST /v1/messages/sendreturnsid→ store{ id, customer, options }.- Learn the WhatsApp id of that menu: on unofficial numbers,
message.sentcarries bothidandmessageId; on official numbers, everystatuses[]item carries youridinbiz_opaque_callback_datanext to thewamid(statuses[].id). - The choice quotes that
messageId—quotedMessageId(unofficial) orcontext.id(official) — so you find the record and the option.
"id": "inv-2041"), step 2 is optional: the row id alone — list_reply.id on official numbers, buttonId on unofficial ones — already tells you what was chosen.
The 24-hour window and cost (official numbers)
- Free-form messages — buttons, lists, carousels, plain text — only deliver on a Meta number while the 24-hour service window is open, that is, within 24 h of the customer’s last message. A bot that answers inbound messages is always inside it.
- To start a conversation yourself (a payment reminder, for example), use an approved template first. When the customer replies, the window opens and the bot can continue with lists and buttons.
- Outside the window the send fails with
META_OUTSIDE_24H_WINDOW. You can check the window before sending withGET /v1/service-window. - Service messages are no longer always free. Since 2026-10-01, Meta gives 1,000 free service messages per month per number and charges the country’s Utility rate after that. Meta bills it, not Pilot Status. See Pricing.
Common mistakes
Next steps
- Send interactive — every button type, carousels,
header/footerrules. - Send a message — full parameter reference for
list. - Receive messages — setting up the webhook.
- Webhook events — canonical and native payloads.