Send Poll

Send an interactive poll with multiple options.

POST
https://api.wawp.net/v2/send/poll?access_token=123456789&chatId=201234567890%40c.us&instance_id=123456789&poll=%7B%0A++%22name%22%3A+%22How+are+you%3F%22%2C%0A++%22options%22%3A+%5B%0A++++%22Awesome%21%22%2C%0A++++%22Good%21%22%2C%0A++++%22Not+bad%21%22%0A++%5D%2C%0A++%22multipleAnswers%22%3A+true%0A%7D&reply_to=null

Authentication Required

Login to swap the placeholders with your real Instance ID and Access Token.

Log In
Test /v2/send/poll endpoint
POST
POST

No query parameters required

This endpoint doesn't expect data in the URL.

Best practices

  • Use "reply_to" to maintain conversation context.

  • Handle distinct message types (text, image, video) appropriately.

  • Implement a robust retry mechanism for failed sends.

Democracy in Chat: Mastering the Interactive Poll Engine

Polls (/v2/send/poll) are the gold standard for gathering structured feedback in a conversational environment. They eliminate the "Decision Fatigue" associated with typing out text responses and provide a clean, visual way for users to express preferences. In a Wawp-powered application, polls act as interactive data entry points that can trigger complex backend workflows based on user selection.


🏗️ The Multi-Option Synchronization Pipeline

When you call the /send/poll endpoint, Wawp initiates a specialized synchronization flow:

  1. Schema Validation: The engine verifies that your options array contains at least two choices and does not exceed the WhatsApp maximum of 12 options. It also ensures each option string is under 255 characters.
  2. Metadata Consistency: The name (your question) and options are serialized into a native WhatsApp Poll packet. Wawp maintains a mapping between these string options and their internal index IDs, ensuring that when a user votes, you get a clean, predictable value in your Webhook.
  3. The MultipleAnswers Logic: Setting multipleAnswers: true instructs the WhatsApp network to render checkboxes instead of radio buttons. This changes the fundamental nature of the engagement from a "Choice" to a "Survey," allowing for more complex data collection.

🛡️ Strategic Best Practices for Feedback Engagement

1. The "Power of Five" Rule

While you can send 12 options, research indicates that conversion drops significantly after five.

  • UX Impact: On mobile screens, long polls require scrolling, which leads to user abandonment. Keep your most important choices in the top three slots.
  • Clarity: Use emojis in your option strings (e.g., "✅ Yes," "❌ No") to provide immediate visual cues that transcend language barriers.

2. High-Fidelity Vote Tracking

A poll is only as good as the data it produces.

  • Monitoring: Always use Webhooks (poll.vote) to capture user interaction. When a user changes their vote, WhatsApp sends a new event. Your backend should be idempotent, updating the user's choice based on the latest poll_vote timestamp.
  • De-duplication: In multipleAnswers mode, remember to handle arrays of choices. Every time a user checks or unchecks a box, a new event is triggered reflecting the entire current state of that user's selections.

3. Contextual Follow-ups

Don't let a vote be the end of the conversation.

  • Workflow: When your webhook receives a vote for Option A, have your system automatically trigger a /v2/send/text or /v2/send/image that specifically addresses that choice. This "Decision-Tree" automation makes the bot feel intelligent and responsive.

🧩 Advanced Use Cases

Real-Time Event Scheduling

Send a poll with time slots for a meeting: "When are you free? 1) 10 AM, 2) 2 PM, 3) 4 PM." As users vote, your system can see which slot has the most votes in real-time and send a confirmation once a consensus is reached.

Customer Satisfaction (CSAT) Surveys

Instead of asking "Rate us 1 to 5," send a poll with descriptive stars or labels: "⭐ Poor" to "⭐⭐⭐⭐⭐ Excellent." The visual feedback of the "Voted" indicator on the user's screen provides a sense of closure that a text-based reply cannot match.


🛠️ Common Pitfalls and Solutions

  • Duplicate Options: Sending a poll with two identical option strings will cause the WhatsApp network to reject the message. Always ensure your options are unique in your backend logic.
  • The "Lost Vote" Trap: Unlike text messages, votes are binary updates. If a user votes while your webhook server is down, you may miss the event. We recommend using our Polling Logs or a robust message queue to process delayed webhook deliveries.
  • Question Length: A question that is too long can be truncated on the chat preview. Keep your name concise and put the detailed context in a preceding text message.

Summary of Capabilities:

  • Deliver native, interactive WhatsApp polls with up to 12 custom options.
  • Support for Single-Choice (Radio) and Multi-Choice (Checkbox) modes.
  • Real-time vote tracking via consistent poll_vote Webhook events.
  • Advanced threading support using the reply_to parameter.
  • High-fidelity synchronization between poll question and selectable choice indices.

Request Parameters

Configure the parameters required to interact with this endpoint. All query and body arguments are listed below with their details.

Request Body

Sent as a JSON object
string

Your unique WhatsApp Instance ID

Example:
string

Your API Access Token

Example:
string

Target phone number or group ID

Example:
object

The poll structure containing name and options.

Example:
string

Message ID to reply to

Example:

Request Samples

Use these ready-to-go code snippets to integrate our API into your project quickly and efficiently. Choose your preferred language and library.

1const baseUrl = "https://api.wawp.net";
2const endpoint = "/v2/send/poll";
3const params = new URLSearchParams({
4 "instance_id": "123456789",
5 "access_token": "123456789"
6}).toString();
7const body = {
8 "chatId": "201234567890@c.us",
9 "poll": {
10 "name": "How are you?",
11 "options": [
12 "Awesome!",
13 "Good!",
14 "Not bad!"
15 ],
16 "multipleAnswers": true
17 },
18 "reply_to": "null"
19};
20
21fetch(`${baseUrl}${endpoint}${params ? '?' + params : ''}`, {
22 method: "POST",
23 headers: { "Content-Type": "application/json" },
24 body: JSON.stringify(body)
25})
26 .then(async (response) => {
27 if (response.ok) {
28 const data = await response.json();
29 console.log("Success:", data);
30 return data;
31 }
32
33 // Error Handling
34 if (response.status === 400) {
35 console.error("Error 400: Bad Request - Missing Required Parameter(s)");
36 }
37 if (response.status === 400) {
38 console.error("Error 400: Bad Request - Invalid Number (Egypt)");
39 }
40 if (response.status === 400) {
41 console.error("Error 400: Bad Request - Invalid Number (Saudi Arabia)");
42 }
43 if (response.status === 400) {
44 console.error("Error 400: Bad Request - Invalid Number (Unknown)");
45 }
46 if (response.status === 400) {
47 console.error("Error 400: Bad Request (XML Format)");
48 }
49 if (response.status === 400) {
50 console.error("Error 400: Bad Request (Plain Text)");
51 }
52 if (response.status === 401) {
53 console.error("Error 401: Unauthorized - Invalid or Missing Access Token");
54 }
55 if (response.status === 401) {
56 console.error("Error 401: Unauthorized (XML Format)");
57 }
58 if (response.status === 404) {
59 console.error("Error 404: Not Found - Session Does Not Exist");
60 }
61 if (response.status === 404) {
62 console.error("Error 404: Not Found (XML Format)");
63 }
64 if (response.status === 429) {
65 console.error("Error 429: Too Many Requests - Rate Limit Exceeded");
66 }
67 if (response.status === 500) {
68 console.error("Error 500: Internal Server Error - Unexpected Failure");
69 }
70 if (response.status === 500) {
71 console.error("Error 500: Internal Server Error (HTML)");
72 }
73 if (response.status === 502) {
74 console.error("Error 502: Bad Gateway - Connection Failed to Upstream");
75 }
76 if (response.status === 502) {
77 console.error("Error 502: Bad Gateway (XML Format)");
78 }
79
80 const errorText = await response.text();
81 console.error(`Error ${response.status}: ${errorText}`);
82 })
83 .catch((error) => console.error("Network Error:", error));
Interactive Samples
Ln 83, Col 1javascript

Expected Responses

Explore all possible responses and outcomes from the server. We have documented each status code with data examples to make success and error handling easier.

Message Sent Successfully
Type:
application/json
object *
string *
object *
number *
boolean *
string *
string *
number *
string *
string *
string *
boolean *
number *
boolean *
boolean *
boolean *
boolean *
boolean *
array *
array *
array *
boolean *
array *

Example

{
"_data": {
  "id": {
    "fromMe": true,
    "remote": "000000000000@c.us",
    "id": "MSG_ID_123456",
    "_serialized": "true_000000000000@c.us_MSG_ID_123456"
    },
  "viewed": false,
  "body": "BASE64_IMAGE_DATA",
  "type": "image",
  "t": 1759108866,
  "from": {
    "server": "c.us",
    "user": "111111111111",
    "_serialized": "111111111111@c.us"
    },
  "to": {
    "server": "c.us",
    "user": "000000000000",
    "_serialized": "000000000000@c.us"
    },
  "ack": 0,
  "isNewMsg": true,
  "star": false,
  "kicNotified": false,
  "caption": "Here's your requested image.",
  "deprecatedMms3Url": "https://example.com/media-url",
  "directPath": "/media/direct/path/example",
  "mimetype": "image/jpeg",
  "filehash": "FILE_HASH_PLACEHOLDER",
  "encFilehash": "ENC_FILE_HASH_PLACEHOLDER",
  "size": 192487,
  "mediaKey": "MEDIA_KEY_PLACEHOLDER",
  "mediaKeyTimestamp": 1759108865,
  "streamable": false,
  "mediaHandle": null,
  "isFromTemplate": false,
  "pollInvalidated": false,
  "isSentCagPollCreation": false,
  "latestEditMsgKey": null,
  "latestEditSenderTimestampMs": null,
  "mentionedJidList": {
    },
  "groupMentions": {
    },
  "isEventCanceled": false,
  "eventInvalidated": false,
  "isVcardOverMmsDocument": false,
  "isForwarded": false,
  "isQuestion": false,
  "questionReplyQuotedMessage": null,
  "questionResponsesCount": 0,
  "readQuestionResponsesCount": 0,
  "labels": {
    },
  "hasReaction": false,
  "disappearingModeInitiator": "chat",
  "disappearingModeTrigger": "chat_settings",
  "productHeaderImageRejected": false,
  "lastPlaybackProgress": 0,
  "isDynamicReplyButtonsMsg": false,
  "isCarouselCard": false,
  "parentMsgId": null,
  "callSilenceReason": null,
  "isVideoCall": false,
  "callDuration": null,
  "callCreator": null,
  "callParticipants": null,
  "isCallLink": null,
  "callLinkToken": null,
  "isMdHistoryMsg": false,
  "stickerSentTs": 0,
  "lastUpdateFromServerTs": 0,
  "invokedBotWid": null,
  "bizBotType": null,
  "botResponseTargetId": null,
  "botPluginType": null,
  "botPluginReferenceIndex": null,
  "botPluginSearchProvider": null,
  "botPluginSearchUrl": null,
  "botPluginSearchQuery": null,
  "botPluginMaybeParent": false,
  "botReelPluginThumbnailCdnUrl": null,
  "botMessageDisclaimerText": null,
  "botMsgBodyType": null,
  "requiresDirectConnection": false,
  "bizContentPlaceholderType": null,
  "hostedBizEncStateMismatch": false,
  "senderOrRecipientAccountTypeHosted": false,
  "placeholderCreatedWhenAccountIsHosted": false,
  "galaxyFlowDisabled": false,
  "links": {
    }
  },
"mediaKey": "MEDIA_KEY_PLACEHOLDER",
"id": {
  "fromMe": true,
  "remote": "000000000000@c.us",
  "id": "MSG_ID_123456",
  "_serialized": "true_000000000000@c.us_MSG_ID_123456"
  },
"ack": 0,
"hasMedia": true,
"body": "Here's your requested image.",
"type": "image",
"timestamp": 1759108866,
"from": "111111111111@c.us",
"to": "000000000000@c.us",
"deviceType": "android",
"isForwarded": false,
"forwardingScore": 0,
"isStatus": false,
"isStarred": false,
"fromMe": true,
"hasQuotedMsg": false,
"hasReaction": false,
"vCards": {
  },
"mentionedIds": {
  },
"groupMentions": {
  },
"isGif": false,
"links": {
  }
}
Bad Request - Missing Required Parameter(s)
Unauthorized - Invalid or Missing Access Token
Not Found - Session Does Not Exist
Too Many Requests - Rate Limit Exceeded
Internal Server Error - Unexpected Failure
Bad Gateway - Connection Failed to Upstream
Previous TopicSend Location
Next TopicSend Poll Vote

Command Palette

Search for a command to run...