Skip to content
Send messages

Send reply buttons

Reply buttons let you offer the recipient up to 3 predefined replies to tap instead of typing. When they pick one, a message.received webhook fires carrying a button_reply object whose id matches the id you set when sending. Use them for confirmations, branching menus, and short multiple-choice questions where each option is a single short label.

This is distinct from CTA URL buttons — those open a link in the device browser; reply buttons stay inside WhatsApp and route back to your webhook.

Terminal window
curl -X POST \
https://api.kirimdev.com/v1/$PHONE_ID/messages \
-H "Authorization: Bearer $KIRIM_KEY" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "+628123456789",
"type": "interactive",
"interactive": {
"type": "reply_buttons",
"body": { "text": "Konfirmasi jadwal workshop besok jam 9?" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "confirm", "title": "Confirm" } },
{ "type": "reply", "reply": { "id": "reschedule", "title": "Reschedule" } },
{ "type": "reply", "reply": { "id": "cancel", "title": "Cancel" } }
]
}
}
}'

The optional header accepts text or a media URL (image / video / document). The footer is short muted text shown beneath the buttons.

{
"messaging_product": "whatsapp",
"to": "+628123456789",
"type": "interactive",
"interactive": {
"type": "reply_buttons",
"header": { "type": "image", "image": { "link": "https://example.com/banner.png" } },
"body": { "text": "Workshop besok jam 9. Pilih salah satu:" },
"footer": { "text": "Tap di luar pesan ini untuk batal." },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "confirm", "title": "Confirm" } },
{ "type": "reply", "reply": { "id": "cancel", "title": "Cancel" } }
]
}
}
}

The recipient’s tap arrives on your webhook as a message.received event. The inbound message has type: "interactive" with a nested button_reply discriminator:

{
"type": "interactive",
"interactive": {
"type": "button_reply",
"button_reply": {
"id": "confirm",
"title": "Confirm"
}
}
}

Route on button_reply.id (stable, set by you) — not on title, which is human-readable and may be localized.

FieldLimit
body.text1–1024 chars, required
header.text (when header.type is text)1–60 chars
header.{image,video,document}.linkValid HTTPS URL
footer.text1–60 chars
action.buttons1–3 entries
Each button.reply.id1–256 chars, unique across the set
Each button.reply.title1–20 chars, unique across the set