Wow! Build your WhatsApp integration. Start free. Register Now
WhatsApp API

An NPS poll in a WhatsApp chat after interaction

The person can score that interaction in the chat they already use. When the interaction has finished, your backend can send that poll through Whapi.Cloud. This use case shows integrators how to implement that flow through the WhatsApp API.

Personal chat, not a group One selectable score
A finished conversation beside a phone whose WhatsApp chat shows an NPS poll the person can answer.
Use case

When to use this flow

The interaction has already finished

Use this flow when the interaction has already finished, not while it is still open.

The score belongs in a personal chat

Use this flow when the person should get the poll in a personal chat, not in a group.

The message is an NPS survey

Use this flow when the message is an NPS survey, not qualifying questions from an ad and not a visit reminder.

WhatsApp chat on a phone showing an NPS poll the person can answer with one score.
Customer experience

The person can score it in chat

After an interaction ends, staff ask for a score by hand or skip the survey, so feedback arrives late or not at all.

After the flow runs, the person sees an NPS poll in their personal WhatsApp chat and can pick one score. Integrators build this result with the WhatsApp API.

Workflow

Send the NPS poll into chat

1

The interaction has finished

Your backend already knows the interaction is over and has the person's phone.

2

Send the NPS poll

POST /messages/poll

sendMessagePoll sends the poll into that personal chat. The title and the score options are on that send. count is 1, so the person picks one score.

Need delivery tracking? A successful send does not mean the person already has the poll. Learn about delivery status →

Prerequisites

Before you run the flow

Connect the WhatsApp number that sends the poll, and authenticate every request with that number's API token. The interaction-finished event stays on your backend.

Optional — go deeper for this flow

API implementation

One call sends the poll

This call is the survey. It puts the poll title and the score options into the personal chat for the person who just finished the interaction.

Get your API token for free after you register on whapi.cloud, and use that token in the code instead of Your_Token from the examples.

Send the NPS poll

Send the NPS poll into the personal chat, with the title and score options for this interaction, so the person can pick one score.

curl --request POST \
     --url https://gate.whapi.cloud/messages/poll \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token' \
     --header 'content-type: application/json' \
     --data '
{
  "to": "447123456789",
  "title": "How likely are you to recommend us?",
  "options": ["0", "10"],
  "count": 1
}
'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/messages/poll",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"to\":\"447123456789\",\"title\":\"How likely are you to recommend us?\",\"options\":[\"0\",\"10\"],\"count\":1}",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token",
    "content-type: application/json"
  ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests

url = "https://gate.whapi.cloud/messages/poll"
payload = {
    "to": "447123456789",
    "title": "How likely are you to recommend us?",
    "options": ["0", "10"],
    "count": 1
}
headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token",
    "content-type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)
print(response.text)
const response = await fetch('https://gate.whapi.cloud/messages/poll', {
  method: 'POST',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    to: '447123456789',
    title: 'How likely are you to recommend us?',
    options: ['0', '10'],
    count: 1,
  }),
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"to\":\"447123456789\",\"title\":\"How likely are you to recommend us?\",\"options\":[\"0\",\"10\"],\"count\":1}");
Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/messages/poll")
  .post(body)
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .addHeader("content-type", "application/json")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/messages/poll");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
request.AddHeader("content-type", "application/json");
request.AddJsonBody(new { to = "447123456789", title = "How likely are you to recommend us?", options = new[] { "0", "10" }, count = 1 });
var response = await client.PostAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	body := []byte(`{"to":"447123456789","title":"How likely are you to recommend us?","options":["0","10"],"count":1}`)
	req, _ := http.NewRequest("POST", "https://gate.whapi.cloud/messages/poll", bytes.NewReader(body))
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")
	req.Header.Set("content-type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
Delivery

Know when the poll arrived

A successful send response does not mean the person already has the poll. The first status visible before a webhook is pending. Later status changes arrive only on statuses.post and statuses.put. If the status stays pending and does not move to sent, delivered, or a later ack, the message was not delivered. Check the payload and the account's permission to send that type.

  • A response from sendMessagePoll is not proof the person has the poll.

  • pending that never moves on means the poll was not delivered.

  • Watch statuses.post and statuses.put for later acks.

  • A vote arrives on messages.post as an action of type vote.

  • Enable messages.patch to see total, each option's count, and voters.

  • read can stay absent until the person replies or saves the number.

What to read on delivery and webhooks

Contact our support if something went wrong
When things break

Handle failures at each step

If the poll send is rejected or not delivered, the person never gets the survey. Retry that send or alert the team, and do not count the survey as sent.

Interaction finished, but the poll failed?

The poll send can be rejected or not delivered after the interaction has already finished. Retry sendMessagePoll or alert the team, and do not count the survey as sent. Clients often mention that our support is responsive. Do not hesitate to ask for help.

Contact our support if something went wrong

Troubleshoot by API step

Status What it means What to do
400 Wrong request parameters
401 Need channel authorization for send message
402 Trial version limit exceeded
403 It is forbidden to send to this group/recipient
429 Too many requests
500 Internal Error
FAQ

Questions integrators ask

No. This flow starts after an interaction has finished. It is not qualifying questions in an inbound ad chat.
No. The message is an NPS survey after the interaction. It is not a visit reminder with those three answers.
If the poll send is rejected or not delivered, retry that send or alert the team and do not count the survey as sent.
No. You set the poll title and the score options on the send. The send does not wait on a pre-written message, and it does not add a charge for that message.
A vote arrives on messages.post as an action of type vote. Enable messages.patch to get total, each option's count, and voters. You can also read that poll with getMessage if you stored its id. That read is not a step in the send on this page.
Supported WhatsApp Features

Everything you need to build WhatsApp automation

Whapi.Cloud gives you access to a complete set of WhatsApp features — messaging, media, groups, channels, webhooks and more. Build bots, automations and integrations without feature limitations.

Chosen by developers

Trusted by 3,300+ developers and SaaS teams

Developers worldwide rely on Whapi.Cloud to build automations, bots, CRM integrations, bulk messaging tools and advanced WhatsApp workflows. Our infrastructure processes millions of API requests with high stability — and grows every month.

Icon of feature

5,5K+

active API channels

Icon of feature

21M+

API requests processed monthly

“Everything is simple, intuitive and easy to navigate. The docs are clear, and all the info I need is right on the screen. Great job.”

roberto k. / Web Developer

“We connected WhatsApp to our workflows using n8n in just a few minutes. No code, no complications- everything worked on the first try.”

Martin p. / Developer

“Whapi.Cloud became a key part of our customer communication. We automated product updates, order notifications and support messages without needing Meta templates or approvals”

Oscar T. / CTO

Decorative bubble