| name | poll-builder |
| description | Self-hosted poll creation tool with real-time results. Use when you need to create a poll, check vote counts, close a poll, export results, or get the shareable link for a poll. Triggers include "create poll", "vote", "poll results", "survey", "collect votes", "share poll", or any task involving polling or voting. |
poll-builder
Create polls, share via link, see live results. Self-hosted.
Base URL
http://localhost:3000
Quick Reference
Create a poll
curl -X POST http://localhost:3000/api/polls \
-H "Content-Type: application/json" \
-d '{
"title": "What should we build next?",
"description": "Vote for the next feature",
"type": "single",
"options": ["Mobile app", "API improvements", "Better docs", "Admin dashboard"],
"endsAt": "2026-03-25T23:59:00Z"
}'
Get all polls
curl http://localhost:3000/api/polls
Get poll results
curl http://localhost:3000/api/polls/1/results
Get public poll (for voting)
curl http://localhost:3000/api/p/k9xm2q4r
Submit a vote
curl -X POST http://localhost:3000/api/p/k9xm2q4r/vote \
-H "Content-Type: application/json" \
-d '{"optionIds": [1]}'
Close a poll
curl -X PATCH http://localhost:3000/api/polls/1/close
Export as CSV
curl http://localhost:3000/api/polls/1/export.csv > results.csv
API Reference
Admin
| Method | Path | Description |
|---|
| GET | /api/polls | List all polls with vote counts |
| GET | /api/polls/:id | Poll detail + options + results |
| POST | /api/polls | Create poll |
| PUT | /api/polls/:id | Update poll |
| DELETE | /api/polls/:id | Delete poll and all votes |
| PATCH | /api/polls/:id/close | Close poll |
| PATCH | /api/polls/:id/reopen | Reopen closed poll |
| GET | /api/polls/:id/results | Detailed results |
| GET | /api/polls/:id/export.csv | CSV download |
Public
| Method | Path | Description |
|---|
| GET | /api/p/:slug | Public poll data |
| POST | /api/p/:slug/vote | Submit vote |
| GET | /api/p/:slug/results | Public results |
Poll Object
{
id: number
slug: string
title: string
description: string | null
type: "single" | "multiple"
status: "open" | "closed"
maxVoters: number | null
endsAt: string | null
requireName: boolean
allowComments: boolean
shareUrl: string
options: PollOption[]
totalVotes: number
createdAt: string
}
Vote Errors
| Error | Meaning |
|---|
already_voted | This voter already voted in this poll |
poll_closed | Poll is closed, no more votes accepted |
max_voters_reached | Voter limit has been hit |
invalid_option | Provided option ID does not belong to this poll |
too_many_options | Multi-choice max exceeded |
WebSocket
Connect to ws://localhost:3000/ws to receive live updates:
{ "type": "subscribe", "slug": "k9xm2q4r" }
{
"type": "update",
"slug": "k9xm2q4r",
"results": [
{ "optionId": 1, "text": "Mobile app", "votes": 396, "pct": 48.1 }
],
"totalVotes": 824
}
Environment Variables
| Variable | Description | Default |
|---|
| PORT | Server port | 3000 |
| DATA_DIR | SQLite directory | ./data |
| BASE_URL | Public URL for share links | http://localhost:3000 |
| LOG_LEVEL | debug/info/warn/error | info |