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. Reads give you the totals and percentages, already worked out, which is what you need to show a result. Individual attendees’ answers stay private.
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).
[
{
"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 }
],
"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. |
requireAttendance |
boolean | No | Only attendees marked present may vote. |
onlyShowToAllowed |
boolean | No | Hide the poll from attendees who may not vote, rather than just disabling it. |
sortNr |
integer | No | Display order within the session. |
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 discards 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 loses those votes - they no longer match any option on offer.
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' discards 24 existing vote(s) for \"Security\" - votes are stored against the option text, so a renamed option loses its ballots."
]
}
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 votes with it. Speakers, sessions and sponsors can be recovered in the console after deletion; polls cannot. The response tells you how many votes went with it:
{ "status": "success", "warnings": ["the poll was deleted permanently along with 50 vote(s)."] }
Use ?dryRun=1 first if you want to see that number before committing.