Home API and integrations | Keys, endpoints and webhooks How to extract Quick Reply button responses from WhatsApp campaigns via API

How to extract Quick Reply button responses from WhatsApp campaigns via API

Last updated on Aug 18, 2026

When to use it

  • When you send a WhatsApp campaign with a template that has quick reply buttons (Quick Reply) and want to know, per campaign, who tapped which button and when.

  • To build campaign and button metrics (response rate, which option was chosen most) from your backend, without having to open conversation by conversation in the interface.

  • It is a server-to-server, read-only endpoint. There is no interface for this in Cloud Chat β€” the data comes out through the API.

Prerequisites

  • An administrator or supervisor Cloud Chat API Access Token. To get yours: click your avatar (bottom-left corner) β†’ Profile Settings and scroll down to the "Access Token" section β€” the field is masked; use the buttons next to it to reveal or copy it. With an agent token the endpoint returns 401/403. Users with ClaudIA-only access do not see this section.

  • Your account's account_id β€” it is the number right after /accounts/ in the Cloud Chat URL. Example: in https://cloudchat.cloudhumans.com/app/accounts/1/dashboard, the account_id is 1.

  • A WhatsApp campaign already sent, whose template has Quick Reply buttons.

  • The campaign's display_id β€” see the section below, "How to find the campaign ID".

How to find the campaign ID (display_id)

The Cloud Chat interface does not display the campaign ID (it does not appear in the listing or in the URL). To find it, use the campaign listing endpoint with the same token:

curl -s 'https://cloudchat.cloudhumans.com/api/v1/accounts/{ACCOUNT_ID}/campaigns?query=CAMPAIGN_TITLE&campaign_type=one_off' \
  -H 'api_access_token: YOUR_API_ACCESS_TOKEN'
  • query searches by the campaign title (the same one shown in the listing in the interface) and campaign_type=one_off restricts to one-off campaigns β€” together they usually return the desired campaign directly.

  • To list all campaigns (bulk extraction), call it without query, paginating:

curl -s 'https://cloudchat.cloudhumans.com/api/v1/accounts/{ACCOUNT_ID}/campaigns?page=1&per_page=100' \
  -H 'api_access_token: YOUR_API_ACCESS_TOKEN'
  • The response comes paginated in the format { "data": [...], "meta": {...} } β€” default 20 per page, per_page maximum 100; iterate page from 1 to meta.total_pages.

  • The id field of each returned campaign is already the display_id you use in the responses endpoint β€” do not confuse it with any internal id.

{ "id": 22081, "title": "My campaign", "campaign_status": "completed", "campaign_type": "one_off" }

How it works

Authentication

api_access_token: YOUR_API_ACCESS_TOKEN

Route

GET https://cloudchat.cloudhumans.com/api/v1/accounts/{ACCOUNT_ID}/campaigns/{DISPLAY_ID}/responses
  • {ACCOUNT_ID} β€” the account id.

  • {DISPLAY_ID} β€” the campaign's display_id.

Query parameters (optional)

  • page β€” page (default 1).

  • per_page β€” items per page (default 100, maximum 500).

Example call

curl -s 'https://cloudchat.cloudhumans.com/api/v1/accounts/7/campaigns/156/responses?page=1&per_page=100' \
  -H 'api_access_token: YOUR_API_ACCESS_TOKEN'

Tip: this curl can be imported directly into Postman (File β†’ Import β†’ Raw text) β€” just replace the token and the ids.

Response

The response has three parts: responses, summary and meta.

{
  "responses": [
    {
      "id": 27749371,
      "content": "Sim, tenho interesse e desejo prosseguir",
      "inbox_id": 174,
      "conversation_id": 1777,
      "message_type": 0,
      "status": "delivered",
      "additional_attributes": {
        "campaign_id": 188,
        "template_button_reply": true,
        "template_button_payload": "Sim, tenho interesse e desejo prosseguir"
      },
      "created_at": 1784781019,
      "sender": {
        "id": 1350835,
        "type": "contact",
        "name": "JoΓ£o da Silva",
        "phone_number": "+5511999998888"
      }
    }
  ],
  "summary": {
    "Sim, tenho interesse e desejo prosseguir": 1
  },
  "meta": {
    "current_page": 1,
    "total_count": 1,
    "total_pages": 1
  }
}
  • responses β€” each item is the contact's reply message (the button tap). Useful fields:

    • content β€” the text of the button that was tapped.

    • sender β€” the contact who replied (name + phone number).

    • additional_attributes.template_button_payload β€” the button's payload (it echoes the button text).

    • conversation_id / created_at β€” where and when the reply happened (created_at is a Unix timestamp, in seconds).

  • summary β€” aggregated count by button text: { "<button text>": <quantity> }. It is the shortcut for the metric "how many people chose each option". The summary always covers the whole campaign, regardless of the page.

  • meta β€” pagination: current_page, total_count (total responses for the campaign), total_pages. Note: total_pages depends on the per_page used. To export all responses, use per_page=500 and iterate page from 1 to total_pages.

Common errors

  • 401 Unauthorized β€” invalid token, expired/regenerated token, or the api_access_token header was not sent.

  • 401/403 β€” the token belongs to an agent user (the endpoint requires an administrator or supervisor on the account).

  • 404 Not Found β€” campaign not found: either the number used is not the display_id (see "How to find the campaign ID"), or the campaign belongs to a different account than the {ACCOUNT_ID} in the URL.

  • Empty responses with the right campaign β€” the template had no Quick Reply buttons, nobody tapped a button yet, or the campaign was sent before the feature's launch (no retroactive data).

Important notes

  • No retroactive history. Only responses recorded from the feature's launch onward appear. Old campaigns are not backfilled retroactively.

  • The analysis identifier is the button text. Since the templates do not define their own payload, the payload simply repeats the button text. Group/analyze by the text (that is what summary does).

  • Counts are per tap, not per unique contact. If the same contact taps more than one button (or the same button more than once), each tap becomes a response and enters the summary. For unique-contact metrics, deduplicate by sender.id on your side.

  • Only campaign Quick Reply button taps count. If the contact replies with free text (instead of tapping a button), that reply does not show up here β€” the link to the campaign only exists when it is a button tap from a campaign send.