WhatsApp API guide

WhatsApp API buttons and lists: what actually works today

Today, the most reliable way to offer clickable options in the WhatsApp API is the list message, which works on any device and returns the choice to your system. Link and call buttons, NativeFlow and carousels round out the kit, but the classic quick reply buttons are no longer available the way they used to be.

By D-API engineering team5 min read

Why this topic confuses so many people

Search for "WhatsApp buttons" and you will find old tutorials showing three reply buttons under a message. That format stopped working reliably outside channels controlled by Meta, and plenty of integrations broke without warning. The result is a market full of promises that fall apart when the customer opens the message.

This page separates what you can ship to production on an unofficial WhatsApp API today, what depends on the device, and what is best avoided.

A map of interactive formats

FormatEndpointReturns a choice?Where it renders
List message/interactive/send/listYes, as list_responsePhone and desktop
Link or call button/interactive/send/templateNo, opens a site or a callVaries by device
NativeFlow/interactive/send/nativeflowDepends on the button typePhone only
Carousel/interactive/send/carouselDepends on the card buttonsVaries by device

The rule of thumb: if the customer's choice needs to come back to your system and work on any screen, use a list. The other formats are add-ons.

Lists: the reliable replacement for reply buttons

A list shows a button (the buttonText) that opens a menu with sections and options. It holds 1 to 10 sections, each with 1 to 10 rows. Each row has a rowId, which is what your system gets back, and a title, which is what the customer reads.

import { DApi } from 'd-api-sdk'

const dapi = new DApi({ apiKey: process.env.DAPI_KEY })

await dapi.interactive.sendList({
  sessionId: 'downtown-clinic',
  to: '14155550123',
  title: 'Your appointment tomorrow',
  description: 'Dr. Patel, 2:30 PM. How would you like to proceed?',
  buttonText: 'Reply',
  footerText: 'Downtown Clinic',
  sections: [
    {
      title: 'Schedule',
      rows: [
        { rowId: 'confirm', title: 'Confirm attendance' },
        { rowId: 'reschedule', title: 'Reschedule', description: 'We will show new times' },
        { rowId: 'cancel', title: 'Cancel' },
      ],
    },
  ],
})

Use stable rowId values with plain ASCII characters. The title can change per campaign or language; the identifier is the contract with your backend.

How the choice gets back to your system

When the customer taps an option, a messages.received event arrives with type: "list_response". It carries the selected_row_id, the chosen title and a summary of the original list. The typical flow looks like this:

  1. Your system sends the list and stores the context (which appointment, which order).
  2. The customer picks an option. The webhook receives the list_response.
  3. The worker reads the selected_row_id, matches it with the context for that number and runs the action: confirm, offer new times, cancel.
  4. If the customer types instead of tapping, treat it as free text and resend the list or bring in an agent.

That fourth step is what separates a flow that works from one that gets stuck. Some people will always type "yes", and your system needs to understand that.

Link and call

The /interactive/send/template endpoint sends a message with url or call buttons. It fits "View order", "Track delivery" or "Call the store", and a URL button pointing to a payment link works well in payment reminder flows. Despite the name, it has nothing to do with the approved templates of the official API.

curl -X POST https://api.d-api.cloud/api/v1/interactive/send/template \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "store",
    "to": "14155550123",
    "content": "Your order 4471 has shipped.",
    "buttons": [
      { "type": "url", "title": "Track order", "url": "https://store.com/order/4471" },
      { "type": "call", "title": "Call the store", "phone": "14155550199" }
    ]
  }'

NativeFlow

Takes 1 to 4 buttons of type quick_reply, url, call and copy. It is the richest format, but it renders on phones only. Use it when you know your audience is in the mobile app, and always keep a text fallback.

Carousel

The carousel shows cards side by side, each with media, text and up to two buttons. It works well as a product showcase.

Limits worth accepting from day one

  • Rendering changes by device and app version. Test on the phone, on WhatsApp Web and on desktop before launching.
  • WhatsApp can change formats without notice. Make the message text self-explanatory, so it still makes sense if the buttons do not show up.
  • Interactive does not replace consent. Sending a list to someone who did not ask for it is still an unsolicited message.

Lists and buttons are usually the visible piece of a larger flow, with triggers, waits and conditions. If that is your case, see automation flows and, to understand when the official API makes more sense, official vs unofficial API.

Frequently asked questions

Can I still send quick reply buttons on WhatsApp?
The classic quick reply buttons, the two or three text options under a message, are not reliably available. To offer choices, use a list message, which works on both phone and desktop.
What is the difference between a list and a button?
A list opens a menu with up to ten sections and ten options in each, and the customer’s choice comes back to your system. Link and call buttons do not return a choice: they open a website or start a call.
Why doesn’t the customer see the buttons on desktop?
Some formats, like NativeFlow, only render in the mobile app. On WhatsApp Web or desktop, the message may arrive without the buttons. If your audience uses desktop a lot, prefer lists or text with a link.
How do I know which option the customer picked?
The choice arrives on the webhook as an incoming message of type list_response, with the identifier of the selected row. Use that identifier, not the displayed text, to decide the next step of the flow.
Do interactive buttons require the official API?
Not for the formats on this page, which are sent through the unofficial connection. On the official WhatsApp API (Meta Cloud API), interactive messages follow the rules and formats set by Meta.

Try D-API's WhatsApp API

3-day trial with full access. No credit card, no lock-in.