Polls API
Create and manage session polls, and read aggregated results.
Manage the polls attendees answer during a session. All endpoints require the standard authentication headers. Write endpoints require the polls:write scope; read endpoints require polls:read.
A poll always belongs to a session, and the session must have hasPoll set to true before attendees can reach it. Set that with /upsertSession.
What this API cannot do
It cannot vote. Attendees vote in the app, and nothing you send here can add, change or clear a vote - attempting it returns an error explaining what to read instead.
You also never see who voted for what. Each answer is stored against the person who gave it, and only they and the session’s moderators can see it. Reads give you the totals and percentages, already worked out, which is what you need to show a result.
GET /getPolls
Returns the event’s polls, ordered by sortNr. Requires polls:read.
| Query parameter | Required | Description |
|---|---|---|
sessionId |
No | Return only the polls attached to this session. |
Each poll comes back with its own settings plus the counted-up result: results, totalVotes (how many answers were given, which can exceed the number of people when a poll allows several picks) and voterCount (how many people answered). voteCounts is the same tally as a plain option-to-number map, without percentages.
Those four are worked out for you and ignored if you send them back, so a poll you fetched, edited and posted to /upsertPoll goes through unchanged.
[
{
"pollId": "p1",
"documentId": "p1",
"sessionId": "s42",
"question": "Which topic should we cover next?",
"options": ["Security", "Performance", "Tooling"],
"maxChoices": 1,
"locked": false,
"visible": true,
"showVotes": true,
"sortNr": 0,
"results": [
{ "option": "Security", "votes": 24, "percentage": 48.0 },
{ "option": "Performance", "votes": 17, "percentage": 34.0 },
{ "option": "Tooling", "votes": 9, "percentage": 18.0 }
],
"voteCounts": { "Security": 24, "Performance": 17, "Tooling": 9 },
"totalVotes": 50,
"voterCount": 50
}
]
GET /getPollResults
Tallies only, without the poll configuration. Requires polls:read.
| Query parameter | Required | Description |
|---|---|---|
pollId |
No | Return one poll’s results. Returns 404 if it does not exist. |
sessionId |
No | Return results for one session’s polls. |
With neither parameter, every poll on the event is returned.
POST /upsertPoll
Creates a poll when pollId is omitted, edits one when it is supplied. Requires polls:write.
| Field | Type | Required on create | Notes |
|---|---|---|---|
pollId |
string | - | Omit to create. |
sessionId |
string | Yes | Must reference an existing session on this event. |
question |
string | Yes | Max 500 characters. |
options |
array of strings | Yes | A JSON array, at least 2 and at most 20 entries. |
maxChoices |
integer | No | At least 1, never more than the number of options. |
locked |
boolean | No | Voting is closed. |
visible |
boolean | No | Shown in the app. |
showVotes |
boolean | No | Attendees see live results. |
whiteListed |
boolean | No | Only whitelisted attendees may vote. Who is on that list is managed in the console, not through this API. |
onlyShowToAllowed |
boolean | No | Hide the poll from attendees who are not on the whitelist, rather than showing it to them disabled. |
sortNr |
integer | No | Display order within the session. |
whiteListed closes a poll, it does not open one
Setting whiteListed to true restricts voting to the people on the session’s whitelist. It does not put anyone on that list, and this API has no endpoint that does: whitelists hold attendee email addresses and are managed only in the console, under the session’s Whitelist button.
So a poll created with whiteListed: true and nothing else is closed to every attendee until someone edits the list in the console. If you are creating polls through an integration, either leave whiteListed off, or make sure the list is in place first.
A poll switched on this way uses the session’s whitelist. The console can also give a single question a list of its own, which shows up on reads as a whitelistId naming that poll - you cannot set it here, because a list you named from outside would be one nothing could fill.
A whitelisted voter may also hand their vote to someone else to cast for them, again from the console or the app. That changes nothing you see: the ballot still counts once, for the person it belongs to.
requireAttendance has been withdrawn
Restricting a poll to attendees scanned in for the session is no longer offered. requireAttendance is no longer settable: send it and it comes back in ignoredFields rather than being applied. It is still returned by reads for polls created while the setting existed.
options is an array, not a comma-separated string
Unlike tags or representativeEmails, poll options are stored and sent as a real JSON array. An option may legitimately contain a comma - "Yes, definitely" - and splitting on commas would silently turn one option into two. Sending a string returns a 400.
Renaming an option orphans its votes
A vote records the option’s wording, not its position in the list. So correcting a typo in an option that people have already voted on strands those votes: they no longer match any option on offer and stop counting towards the result.
The change is still saved, and the response tells you what it cost, so decide before you edit a live poll:
{
"status": "success",
"pollId": "p1",
"created": false,
"warnings": [
"'options' changing 'options' orphans 24 existing vote(s) for \"Security\" - a ballot records the option's wording, so a renamed option stops counting towards any answer."
]
}
Putting the original wording back restores those votes exactly, since the answers themselves were never deleted.
Example request
curl -X POST "https://api.event-vault.com/upsertPoll" \
-H "x-api-key: $EV_API_KEY" \
-H "x-client-id: $EV_CLIENT_ID" \
-H "x-event-id: $EV_EVENT_ID" \
-H "x-timestamp: $(python3 -c 'import time;print(int(time.time()*1000))')" \
-H "Content-Type: application/json" \
-d '{
"sessionId": "s42",
"question": "Which topic should we cover next?",
"options": ["Security", "Performance", "Tooling"],
"visible": true,
"showVotes": true
}'
POST /deletePoll
Requires polls:write.
{ "pollId": "p1" }
Deleting a poll is permanent, and it takes the answers with it. Speakers, sessions and sponsors can be recovered in the console after deletion; polls cannot. The response tells you how many went:
{ "status": "success", "warnings": ["the poll was deleted permanently along with 50 ballot(s)."] }
If the poll kept a whitelist of its own, that list goes too, and the response says so. The session’s own whitelist and any other question’s list are left alone, as is anyone who was only ever holding someone else’s vote.
Use ?dryRun=1 first if you want to see what would go before committing.