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/v1

Authentication

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

POST/polls

Create a new poll. Returns the poll with its public URL and a QR code URL.

Body parameters

NameTypeRequiredDescription
titlestringRequired1–200 characters.
descriptionstringOptionalOptional, up to 1000 characters.
typeenumOptional · default multiple_choiceOne of multiple_choice, yes_no, rating.
optionsarray<{ text: string }>RequiredBetween 2 and 10 options. For yes_no / rating types options are auto-set; you can omit them.
settings.allowMultipleVotesbooleanOptional · default falseAllow each voter to cast more than one vote.
settings.showResultsbooleanOptional · default trueWhether voters can see the running tally.
settings.resultsVisibilityenumOptional · default alwaysOne of always, after_vote, after_closing.
settings.expiresAtISO 8601 datetimeOptionalWhen 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/?…"
  }
}
GET/polls

List polls created by the authenticated user, newest first.

Query parameters

NameTypeRequiredDescription
limitintegerOptional · default 50Max 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/?…"
    }
  ]
}
GET/polls/{id}

Get a single poll with its options and current vote tallies.

Path parameters

NameTypeRequiredDescription
idstringRequiredThe 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
}
GET/stats

Account-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, or null if 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." } }
StatusCodeMeaning
401UNAUTHORIZEDMissing, malformed, or revoked API key.
403PLAN_REQUIREDYour plan doesn't include API access.
404Resource not found, or not owned by you.
429Rate-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.

Contact us