REST API · v1
API Documentation
Create and read polls programmatically. Bearer-token auth, JSON in, JSON out.
Getting started
All endpoints live under one base URL. Requests and responses are JSON. Every request must include a Bearer token — see Authentication.
Base URL
https://onetapvote.com/api/v1Authentication
Generate an API key from your dashboard settings and send it in the Authorization header.
Authorization: Bearer otv_live_YOUR_KEY- •API access requires a Pro or Business plan.
- •Rate limits per API key: 10 writes/min and 60 reads/min.
- •Keys are shown once on creation — store them in a secret manager.
Endpoints
/pollsCreate a new poll. Returns the poll with its public URL and a QR code URL.
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
| title | string | Required | 1–200 characters. |
| description | string | Optional | Optional, up to 1000 characters. |
| type | enum | Optional · default multiple_choice | One of multiple_choice, yes_no, rating. |
| options | array<{ text: string }> | Required | Between 2 and 10 options. For yes_no / rating types options are auto-set; you can omit them. |
| settings.allowMultipleVotes | boolean | Optional · default false | Allow each voter to cast more than one vote. |
| settings.showResults | boolean | Optional · default true | Whether voters can see the running tally. |
| settings.resultsVisibility | enum | Optional · default always | One of always, after_vote, after_closing. |
| settings.expiresAt | ISO 8601 datetime | Optional | When the poll auto-closes. Capped by your plan's max expiry. |
curl -X POST https://onetapvote.com/api/v1/polls \
-H "Authorization: Bearer otv_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Pick a date for our retreat",
"description": "Choose what works best.",
"type": "multiple_choice",
"options": [
{ "text": "May 12" },
{ "text": "May 19" },
{ "text": "May 26" }
],
"settings": {
"allowMultipleVotes": false,
"showResults": true,
"resultsVisibility": "always"
}
}'Response · 201 Created
{
"poll": {
"id": "clxyz123",
"title": "Pick a date for our retreat",
"description": "Choose what works best.",
"type": "multiple_choice",
"status": "active",
"createdAt": "2026-04-16T09:23:11.000Z",
"expiresAt": null,
"url": "https://onetapvote.com/polls/clxyz123",
"qrCodeUrl": "https://api.qrserver.com/v1/create-qr-code/?…"
}
}/pollsList polls created by the authenticated user, newest first.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| limit | integer | Optional · default 50 | Max number of polls to return (1–100). |
curl https://onetapvote.com/api/v1/polls?limit=20 \
-H "Authorization: Bearer otv_live_YOUR_KEY"Response · 200 OK
{
"polls": [
{
"id": "clxyz123",
"title": "Pick a date for our retreat",
"description": "Choose what works best.",
"type": "multiple_choice",
"status": "active",
"createdAt": "2026-04-16T09:23:11.000Z",
"expiresAt": null,
"url": "https://onetapvote.com/polls/clxyz123",
"qrCodeUrl": "https://api.qrserver.com/v1/create-qr-code/?…"
}
]
}/polls/{id}Get a single poll with its options and current vote tallies.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The poll id returned from create. |
curl https://onetapvote.com/api/v1/polls/clxyz123 \
-H "Authorization: Bearer otv_live_YOUR_KEY"Response · 200 OK
{
"poll": {
"id": "clxyz123",
"title": "Pick a date for our retreat",
"description": "Choose what works best.",
"type": "multiple_choice",
"status": "active",
"createdAt": "2026-04-16T09:23:11.000Z",
"expiresAt": null,
"url": "https://onetapvote.com/polls/clxyz123",
"qrCodeUrl": "https://api.qrserver.com/v1/create-qr-code/?…"
},
"options": [
{ "id": "opt_1", "text": "May 12", "position": 0, "votes": 14 },
{ "id": "opt_2", "text": "May 19", "position": 1, "votes": 9 },
{ "id": "opt_3", "text": "May 26", "position": 2, "votes": 3 }
],
"totalVotes": 26
}/statsAccount-wide rollup: poll counts by status, total votes, last-30-day activity, and your top poll. Useful for building dashboards or automating reports.
curl https://onetapvote.com/api/v1/stats \
-H "Authorization: Bearer otv_live_YOUR_KEY"Response · 200 OK
{
"stats": {
"totalPolls": 42,
"activePolls": 8,
"closedPolls": 32,
"draftPolls": 2,
"newPollsLast30Days": 12,
"totalVotes": 1893,
"votesLast30Days": 412,
"topPoll": {
"id": "clxyz123",
"title": "Pick a date for our retreat",
"voteCount": 234,
"url": "https://onetapvote.com/polls/clxyz123"
}
}
}Returned fields
totalPolls·activePolls·closedPolls·draftPolls— counts by status.newPollsLast30Days— polls created in the last 30 days.totalVotes·votesLast30Days— vote counts across all your polls.topPoll— your single highest-vote poll, ornullif you have none.
Errors
Errors return a JSON body with an error object. Inspect error.code for a programmatic identifier.
{ "error": { "code": "PLAN_REQUIRED", "message": "API access requires a Pro or Business plan." } }| Status | Code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing, malformed, or revoked API key. |
| 403 | PLAN_REQUIRED | Your plan doesn't include API access. |
| 404 | — | Resource not found, or not owned by you. |
| 429 | — | Rate-limit hit (10 writes/min, 60 reads/min per key). |
Need an endpoint we don't cover yet?
Tell us what you're building — we ship requests fast.