Documentation

Q&A API

Read, post, moderate, and answer audience questions.

Manage the audience questions asked during a session. All endpoints require the standard authentication headers. Write endpoints require the qa:write scope; the read endpoint requires qa:read.

Questions are stored per session, so sessionId is required on every call. The session must have hasLiveQA set to true before attendees can reach the Q&A - set that with /upsertSession.

What this API cannot do

It cannot upvote. Attendees upvote questions in the app, and nothing you send here can change a question’s vote count. You can post, edit, approve, reject, answer and delete questions.


A question has one status

Every question is in exactly one of four states, and you set it with a single status value:

status Meaning
pending Asked, not yet moderated. The default for a new question.
approved Visible to the audience.
rejected Hidden by a moderator.
answered Answered on stage. Implies approved, and requires answer text.

Behind the scenes a question stores these as separate on/off flags, and it is possible for a careless integration to mark one both approved and rejected. This API will not let that happen: it only accepts status, and sets the flags for you. Sending approved, rejected or answered directly returns an error pointing you at status.

Reads give you status directly, so you never have to work it out.


GET /getQuestions

Returns a session’s questions, highest-voted first. Requires qa:read.

Query parameter Required Description
sessionId Yes The session whose questions you want.
[
  {
    "questionId": "q7",
    "documentId": "q7",
    "sessionId": "s42",
    "question": "How does this scale past 10k attendees?",
    "answer": "We shard by event, so it scales linearly.",
    "status": "answered",
    "score": 31,
    "voterCount": 31,
    "approved": true,
    "rejected": false,
    "answered": true
  }
]

Questions come back most-upvoted first.


POST /upsertQuestion

Creates a question when questionId is omitted, edits one when it is supplied. Requires qa:write.

Field Type Required on create Notes
sessionId string Yes Must reference an existing session. Required on edit too.
questionId string - Omit to create.
question string Yes Max 500 characters.
answer string No Max 500 characters. Required when status is answered.
status enum No pending, approved, rejected or answered. New questions default to pending.

Marking a question answered with no answer text - neither in this request nor already saved - is rejected, because attendees would see it flagged as answered with nothing there.

Questions you post through the API start with no upvotes and no attendee attached to them, since they did not come from someone in the audience.

Example: approve and answer in one call

curl -X POST "https://api.event-vault.com/upsertQuestion" \
  -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",
        "questionId": "q7",
        "status": "answered",
        "answer": "We shard by event, so it scales linearly."
      }'

POST /deleteQuestion

Requires qa:write.

{ "sessionId": "s42", "questionId": "q7" }

Deletion is permanent - the same as deleting a question in the console. There is no recycle bin for questions, so reject it instead if you might want it back.