Skip to Content
Polls

Polls

WhatsApp polls are end-to-end encrypted — vote events arrive as opaque pollUpdateMessages. Raw-Baileys adapters make you persist each poll’s messageSecret and decrypt votes yourself. Here, Zaileys decrypts votes natively: no bookkeeping, no TTLs, and it works across restarts for any poll this account sent.

Sending a poll

import { requireZaileysAdapter } from 'chat-adapter-zaileys' const wa = requireZaileysAdapter(thread) const poll = await wa.sendPoll({ threadId: thread.id, question: 'What time works for the call?', options: ['10:00', '14:00', '17:00'], selectableCount: 1, // any other value allows multiple selections })

Receiving votes

// every poll this account sent wa.onPollVote((vote) => { console.log(vote.voter.userName, '→', vote.selectedOptions) }) // scoped to one (or several) polls wa.onPollVote(poll.id, async (vote) => { await thread.post(`${vote.voter.userName} picked ${vote.selectedOptions[0]}`) }) wa.onPollVote([pollA.id, pollB.id], handler)

The ZaileysPollVote payload:

FieldTypeNotes
threadIdstringWhere the poll lives
pollMessageIdstringId of the original poll message
questionstring | nullRecovered from the message store when available
optionsstring[]Same — empty if the poll left the store
selectedOptionsstring[]Current selection; empty = vote cleared
voterAuthorChat SDK author shape
rawPollVotePayloadThe Zaileys payload

Votes as messages

By default (forwardPollVotes: true) each non-empty vote is also forwarded to the regular message pipeline with the selected options as text — so onSubscribedMessage bots see poll answers without extra code:

bot.onSubscribedMessage(async (thread, message) => { // a vote for "14:00" arrives as message.text === "14:00" })

Set forwardPollVotes: false to keep votes exclusively in onPollVote.

Polls sent through any Zaileys path — wa.sendPoll, native(threadId).poll(…), even client.send(jid).poll(…) outside the adapter — all produce decryptable votes. There is no “tracked polls” registry to manage.