Documentation

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.