Polls is a public JSON REST API that lets you create, view, edit, delete and vote on polls. Voting is limited to one vote per IP address per poll. Polls can be configured by setting expiry time, results visibility and private status. The API also provides the ability to list, search and sort public polls.
I wanted to write an API that makes it simple for anyone to create polls and vote without need for user accounts or logins. My goals were also to implement IP based voting limitation, rate limiting, write tests, and deploy the API(to an EC2 instance in this case).
I also made a React app that uses the Polls API. You can try it out at https://www.polls.ovh/
Requirements:
- Bash
- Docker
git clone https://github.com/ivcp/polls.git
cd polls
- create a
.env
file in the repository's root directory (see.env.example
) - make sure Docker is running
bash build.sh
curl localhost/v1/healthcheck
to check if it's working
Creates new poll. It's necessary to provide a question and at least two options. Option positions must also be provided and start at 0.
Example request body:
{
"question": "Favourite color?",
"options": [
{ "value": "Red", "position": 0 },
{ "value": "Blue", "position": 1 }
]
}
Optionally you can provide:
"description"
- poll description."expires_at"
- time when the poll expires. Must be at least two minutes in the future. ISO 8601 string e.g. "2024-02-05T14:48:00.000Z"."is_private"
- private polls are only accessible by link."results_visibility"
- when results can be seen. Accepted values: "always", "after_vote", "after_deadline".
Example response:
{
"poll": {
"id": "6df661aa-4f3f-4281-8b69-da430a8ebad4",
"question": "Favourite color?",
"description": "",
"options": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"value": "Red",
"position": 0
},
{
"id": "8ea93888-8002-4889-94a1-24d75e10c07d",
"value": "Blue",
"position": 1
}
],
"created_at": "2024-02-26T17:19:44Z",
"updated_at": "2024-02-26T17:19:44Z",
"expires_at": "",
"results_visibility": "always",
"is_private": false,
"token": "ZLCQIKYQ4MT7K2NJCRQWC4KMMU"
}
}
Show individual poll.
Example response:
{
"poll": {
"id": "6df661aa-4f3f-4281-8b69-da430a8ebad4",
"question": "Favourite color?",
"description": "",
"options": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"value": "Red",
"position": 0
},
{
"id": "8ea93888-8002-4889-94a1-24d75e10c07d",
"value": "Blue",
"position": 1
}
],
"created_at": "2024-02-26T17:19:44Z",
"updated_at": "2024-02-26T17:19:44Z",
"expires_at": "",
"results_visibility": "always",
"is_private": false
}
}
List public polls.
Accepts query parameters:
search
- search by questionpage_size
- set number of results per page (default 20)page
- set current page number (default 1)sort
- sort by:-created_at
latest created (default)created_at
oldest created-question
poll question in descending alphabetical orderquestion
poll question in ascending alphabetical order
Example response:
{
"metadata": {
"current_page": 1,
"page_size": 20,
"first_page": 1,
"last_page": 1,
"total_records": 1
},
"polls": [
{
"id": "6df661aa-4f3f-4281-8b69-da430a8ebad4",
"question": "Favourite color?",
"description": "",
"options": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"value": "Red",
"position": 0
},
{
"id": "8ea93888-8002-4889-94a1-24d75e10c07d",
"value": "Blue",
"position": 1
}
],
"created_at": "2024-02-26T17:19:44Z",
"updated_at": "2024-02-26T17:19:44Z",
"expires_at": "",
"results_visibility": "always",
"is_private": false
}
]
}
Vote for option.
Example response:
{
"message":"vote successful"
}
Show results for poll.
Example response:
{
"results": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"value": "Red",
"position": 0,
"vote_count": 0
},
{
"id": "117d4ef6-322e-436c-9c6b-46964e10b8c3",
"value": "Green",
"position": 2,
"vote_count": 0
},
{
"id": "8ea93888-8002-4889-94a1-24d75e10c07d",
"value": "Blue",
"position": 1,
"vote_count": 1
}
]
}
Token is required for following endpoints. Token is generated when a poll is created and must be included in the Authorization header.
Update poll question, description or expiration time. Supports partial updates.
Example request body:
{
"description": "We all know there are only two colors."
}
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"poll": {
"id": "6df661aa-4f3f-4281-8b69-da430a8ebad4",
"question": "Favourite color?",
"description": "We all know there are only two colors.",
"options": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"value": "Red",
"position": 0
},
{
"id": "8ea93888-8002-4889-94a1-24d75e10c07d",
"value": "Blue",
"position": 1
}
],
"created_at": "2024-02-26T17:19:44Z",
"updated_at": "2024-02-26T19:11:00Z",
"expires_at": "",
"results_visibility": "always",
"is_private": false
}
}
Delete a poll.
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"message": "poll successfully deleted"
}
Add option to poll.
Example request body:
{
"value":"Green"
}
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"message":"option added successfully"
}
Update an existing option's value.
Example request body:
{"value":"Yellow"}
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"message":"option updated successfully"
}
Update option positions.
Example request body:
{
"options": [
{
"id": "802c593f-5f79-44f7-80d1-4cc4e40ddcec",
"position": 2
},
{
"id": "117d4ef6-322e-436c-9c6b-46964e10b8c3",
"position": 0
}
]
}
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"message":"option updated successfully"
}
Delete option.
Headers example:
Authorization: Bearer ZLCQIKYQ4MT7K2NJCRQWC4KMMU
Example response:
{
"message":"option deleted successfully"
}
- Go
- Postgres
- Docker
- Caddy
If you'd like to contribute, please fork the repository and open a pull request to the master
branch.