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.
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" } } ] } } }'import { Kirim } from '@kirimdev/sdk'
const kirim = new Kirim({ apiKey: process.env.KIRIM_KEY! })const phone = kirim.phoneNumbers(process.env.PHONE_ID!)
await phone.messages.send({ 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' } }, ], }, },})With a header and footer
Section titled “With a header and footer”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" } } ] } }}Handle the reply
Section titled “Handle the reply”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.
Limits
Section titled “Limits”| Field | Limit |
|---|---|
body.text | 1–1024 chars, required |
header.text (when header.type is text) | 1–60 chars |
header.{image,video,document}.link | Valid HTTPS URL |
footer.text | 1–60 chars |
action.buttons | 1–3 entries |
Each button.reply.id | 1–256 chars, unique across the set |
Each button.reply.title | 1–20 chars, unique across the set |
See also
Section titled “See also”- Send interactive CTA URL buttons — for opening a link
- Send interactive lists — for >3 options
- Webhook events:
message.received - API Reference — Send a WhatsApp message (see the Interactive → Reply buttons request-body tab)