Polls and Quizzes API
You can create and publish polls, quizzes and rating scales via API — full parity with the Widgets → Polls and Quizzes admin panel, so external systems can publish engagement materials automatically.
A poll cluster is the unit you publish: it targets one or more rooms, carries the scheduling, and contains one question (a standalone poll) or several questions in a row (a series). Each poll inside a cluster is a single question with its options.
Required headers for all endpoints
Regional endpoints: Replacechatbackend.watchers.iowith the endpoint matching your project region. See Supported Regions.
Region Endpoint Europe (default) chatbackend.watchers.ioNorth America chatbackend.us.watchers.ioSouth America chatbackend.sa.watchers.ioAsia chatbackend.hk.watchers.ioAfrica chatbackend.za.watchers.io
| Parameter | Description |
|---|---|
x-api-key | Your public API key for the project |
Authorization | Bearer <token> from the admin panel (Settings → Bearer tokens) for back-to-back integrations |
Poll types
| Type | Description |
|---|---|
POLL | A regular poll — no correct answer. Single or multiple choice (isMultiple). |
QUIZ | A poll with correct answer(s). Mark correct options with isRight: true. |
RATING | A rating scale. Set ratingScale (e.g. 3, 5, 10). |
To any type you can add a free-text custom answer option (isCustom: true).
Endpoints
POST /external/poll-cluster — create a poll/series
/external/poll-cluster — create a poll/seriesCreates a poll cluster together with its questions and targets it to rooms.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Internal name of the cluster |
isStandalone | boolean | No | true for a single question, false (default) for a series |
isActive | boolean | No | Default true |
roomIds | string[] | No | External room IDs to publish to (JSON array or CSV file) |
startTime | ISO datetime | No | Scheduled publish time. If omitted — published immediately |
endTime | ISO datetime | No | Auto-finish time |
dailyWindowStart | HH:MM | No | Show only after this time each day |
dailyWindowEnd | HH:MM | No | Hide after this time each day |
polls | Poll[] | No | The questions (see Poll object) |
GET /external/poll-cluster — list
/external/poll-cluster — listQuery parameters: limit (default 20), offset (default 0), order (default id_desc). Returns { pollClusters, pageCount }.
GET /external/poll-cluster/:id — get one
/external/poll-cluster/:id — get oneReturns the cluster with its rooms and polls.options.
PATCH /external/poll-cluster/:id — update
/external/poll-cluster/:id — updateSame body as create (all fields optional). Changing scheduling fields reschedules the cluster.
DELETE /external/poll-cluster/:id — delete
/external/poll-cluster/:id — deletePOST /external/poll-cluster/:id/poll — add a question to a cluster
/external/poll-cluster/:id/poll — add a question to a clusterBody = Poll object.
PATCH /external/poll/:pollId — update a question
/external/poll/:pollId — update a questionPartial Poll object. Options sent with an id are updated; options without id are created.
DELETE /external/poll/:pollId — delete a question
/external/poll/:pollId — delete a questionPoll object
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The question |
type | POLL | QUIZ | RATING | Yes | See Poll types |
isMultiple | boolean | No | Allow multiple selected options. Default false |
ratingScale | integer ≥ 1 | For RATING | Number of points on the scale |
pic | string | No | Image URL for the question (or upload, see Media) |
options | Option[] | Yes | At least 1 (see Option object) |
Option object
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Answer text |
pic | string | No | Image URL for the answer |
isRight | boolean | No | Correct answer (for QUIZ). Default false |
isCustom | boolean | No | Turns this option into a free-text input. Default false |
customPlaceholder | string | No | Placeholder for the custom input |
customMinLength | integer ≥ 0 | No | Minimum length of the custom text |
customMaxLength | integer ≥ 1 | No | Maximum length of the custom text |
Media
Send requests as multipart/form-data. Either pass pic as a URL string, or upload a file:
- Poll endpoints (
/poll,/poll/:pollId): attach the image in thepicfield. - Cluster create/update: give each poll a temporary
id, then attach its image in a field namedpic_<id>. Uploaded images are resized automatically (max 600 px).
Example — a quiz published to two rooms
{
"name": "Match prediction",
"isStandalone": true,
"roomIds": ["room-123", "room-456"],
"startTime": "2026-07-01T18:00:00Z",
"endTime": "2026-07-01T20:00:00Z",
"polls": [
{
"text": "Who scores first?",
"type": "QUIZ",
"options": [
{ "text": "Team A", "isRight": true },
{ "text": "Team B", "isRight": false },
{ "text": "Other", "isCustom": true, "customPlaceholder": "Your guess", "customMaxLength": 50 }
]
}
]
}Example — a rating scale
{
"name": "Post-match rating",
"isStandalone": true,
"roomIds": ["room-123"],
"polls": [
{
"text": "Rate the match",
"type": "RATING",
"ratingScale": 5,
"options": [{ "text": "Rating" }]
}
]
}