Interactive messages with the WhatsApp Cloud API
Meta's official WhatsApp API lets you send native buttons, lists, and carousels — no middleware BSP required. Here's what you need to integrate and the ID pattern that keeps conversation state off the server.
The 4 message types
All types use POST /messages with "messaging_product": "whatsapp". The 24h window starts from the user's last message.
POST https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/jsonInteractive buttons
The reply.id field is returned exactly as sent in the webhook — use it to identify the action without any server-side state.
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "interactive",
"interactive": {
"type": "button",
"body": { "text": "Como prefere receber o pedido?" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "delivery", "title": "🛵 Entrega" } },
{ "type": "reply", "reply": { "id": "pickup", "title": "🏠 Retirada" } }
]
}
}
}IDs as a state machine
The cleanest way to manage conversation flow is to encode the action directly in the button id with prefixes. In the webhook, parse the prefix and execute the action — the button carries the intent, no server state needed.
restaurant:<uuid> → selecionar restaurante
category:<uuid> → filtrar cardápio
item:<uuid> → adicionar ao carrinho
cart:view → mostrar carrinho
cart:checkout → iniciar checkout
cart:remove:<n> → remover item n
confirm:yes → confirmar ação
order:<uuid> → status do pedidoEssential checklist
- Credentials in environment variables, never in code
- Respond to the webhook with HTTP 200 immediately — Meta retries if it doesn't receive a response in 20s
- Deduplicate by
message.id— Meta may deliver the same message more than once - Wrap interactive sends in
try/catchwith plain text fallback - Carousel: minimum 2 cards, all with the same number of buttons, JPEG 1:1 images
Full reference
The file covers all payloads with exact character limits, webhook structure for each type (including the carousel quick_reply difference), fallback strategy, and carousel image rules.