Ownware
HomeVoteraAPI
Votera · API

Votera API, as shipped in the download

Votera REST API & Webhooks (v2.0)

Votera ships a JSON REST API and signed webhooks so your support desk, CRM or CI can file feedback,
move items across the roadmap, and reply — without anyone opening the board.

Migrating from Canny (or Nolt / Featurebase)

Export your posts to CSV and import them with their vote counts intact.
Admin → Import accepts title (required), body, board, votes, author, with the usual
header-name aliases (Post Title, Description, Vote Count, …) and a dry-run report first.

Those tools export a vote count, not individual voters, while Votera stores one row per voter.
The import therefore synthesises one placeholder voter per counted vote, keyed imported:<post>:<n>,
so a migrated post keeps its standing on the board on day one. Real visitors vote on top of that
normally — a synthetic key can never collide with a real one.

Authentication

Authorization: Bearer apk_...

Create a key in Settings → API & Webhooks; shown once, stored hashed.

Endpoints

Method & pathWhat it does
GET /api/pingVerify a key
GET /api/boardsBoards and statuses — the status ids you need to move things
GET /api/posts?board= (slug or id) · ?status= (label or id) · `?sort=top\new\trending`
POST /api/postsFile a post as the key's user
GET /api/posts/{id}One post
POST /api/posts/{id}/statusMove it across the roadmap
GET /api/posts/{id}/commentsPublic comments
POST /api/posts/{id}/commentsReply as the team
GET /api/openapi.jsonOpenAPI 3.0

File a post from your helpdesk

curl -X POST https://feedback.example.com/api/posts \
-H "Authorization: Bearer apk_..." -H "Content-Type: application/json" \
-d '{"board":"feature-requests","title":"Bulk export","body":"Asked by 3 customers this week."}'

Move it when you start work

curl -X POST https://feedback.example.com/api/posts/42/status \
-H "Authorization: Bearer apk_..." -H "Content-Type: application/json" \
-d '{"status_id":3}'

status_id must be a real status (GET /api/boards lists them); send null to clear it.

What the API deliberately will NOT give you

  • Author emails. A public board collects them so posters can be notified, not so an integration

can build a mailing list. author_email is never serialized.

  • Internal staff notes. Notes written with the "internal" flag stay in the admin UI. The comments

endpoint calls the same reader the public board uses, with internal notes excluded.

Webhooks

EventFires when
post.createdA post is filed (UI or API)
post.status_changedA post moves — payload carries previous_status_id
comment.createdA public comment is added

X-Votera-Event: post.status_changed
X-Votera-Signature: sha256=<hmac_sha256(raw_body, your_webhook_secret)>

Errors

CodeMeaning
401Missing, unknown or revoked key
404No such post / board
422Validation — detail names the problem

Own It 3.0

MCP — the agent endpoint

Votera speaks MCP (Model Context Protocol) at POST /mcp, authenticated with the same revocable
API keys the REST API uses. Stateless streamable-HTTP: one JSON-RPC message per request.

GET /mcp answers 405 with Allow: POST — deliberately before the API-key check, so a
client probing for MCP support with no credentials learns the transport is here rather than being
told 401, which would mean "no MCP endpoint". The unauthenticated hint names no tools.

ToolWrites?What it does
list_boardsnoThe boards and how many open ideas each holds.
list_postsnoIdeas with vote counts and status. Sort by top / trending / new.
post_detailnoOne idea, its body, its tally and its public comments.
create_postYESFiles an idea, through the public form's own validation.
set_statusYESMoves an idea to a status, by label.
top_voted_reportnoThe tally: most-wanted ideas and the status mix.

Connect it to an assistant

Mint the key in the app first: Settings → API keys. Choose Read only when the assistant should
answer questions but never change anything — the endpoint then lists only the read tools and refuses the
rest by name, so a careless prompt cannot write. Full access behaves as before.

Every client needs the same three facts, and nothing in the handshake is vendor-specific:

The addresshttps://feedback.example.com/mcp
The keyheader Authorization: Bearer apk_xxxx
The transportMCP over streamable HTTP, stateless

Claude — one command, or the same URL and header as a custom connector in the desktop and web apps:

claude mcp add --transport http votera https://feedback.example.com/mcp \
  --header "Authorization: Bearer apk_xxxx"

ChatGPT and the OpenAI API — one entry in the Responses API's tools array (in ChatGPT itself, the
same URL and key go in as a connector):

{
  "type": "mcp",
  "server_label": "votera",
  "server_url": "https://feedback.example.com/mcp",
  "authorization": "apk_xxxx",
  "require_approval": "never"
}

A client that keeps its servers in a config file — Own Your AI, editors like VS Code and Cursor, and
most desktop clients read a list like this:

{
  "mcpServers": [
    { "id": "votera", "name": "Votera", "url": "https://feedback.example.com/mcp",
      "token": "apk_xxxx", "enabled": true }
  ]
}

A local model, n8n, or your own code — n8n's MCP Client node takes the URL and the same
Authorization: Bearer header; a model running on your own machine reaches it through any MCP client, so
nothing leaves your network at all. Writing it yourself is one POST of JSON-RPC 2.0:

curl -X POST https://feedback.example.com/mcp \
  -H "Authorization: Bearer apk_xxxx" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Any client that speaks MCP's streamable-HTTP transport works, including ones that do not exist yet:
Votera implements the protocol, not an integration with a particular vendor.

⛔ There is deliberately no cast_vote tool

This was a design decision, and it is worth stating plainly: an agent cannot vote. A vote here is
the entire signal — the product exists to tell you what people actually want. Votes are keyed to a
browser or an address rather than a verified identity, and the rate limiter exists because a real
attack of 1,239 votes per minute from one machine was measured. An authenticated voting endpoint
would industrialise exactly that. An agent may read the tally and file an idea; the wanting has to
come from someone who wants it.

What the endpoint refuses

  • create_post uses the public form's rules, so a two-character title is refused with the same

sentence a visitor would see.

  • An unknown status names the valid ones. An agent told only "invalid" learns nothing.
  • post_detail does not return author email addresses. An agent reading a public board has no

business collecting the address of everyone who filed a bug.

Verified voting

With Settings → Voting → require an email and confirm the address first, a vote is held
until a link sent to that address is clicked (GET /vote/verify/{token}, single use, two-day life).

The anonymity property is preserved, and it is the point. The voter key is a salted hash of the
address; the verification row keys on that same hash and has no email column. So the database can
answer "did someone at this address verify?" and can never answer "which address voted for what".
The audit trail redacts the voter key for the same reason.

Scheduled changelog releases

An entry whose published_at is in the future is not public yet. The public page, the widget and
the release feed all read Board::changelog(true), which now compares the date against now — so a
scheduled entry becomes visible through the same query an immediate one does. There is no second
publish path to keep in step.

Scheduled backup

GET /backup/scheduled?t=<token>

A token-guarded URL for cron. The token is minted once in Backup, shown once, stored only as a
SHA-256 hash. It writes a dated JSON backup, keeps the newest N and deletes older ones. Password
hashes, API-key hashes, webhook secrets, the OIDC client secret, the backup and calendar tokens and
2FA seeds are blanked — the same list /backup.json uses.

Release calendar

GET /feed/releases.ics?t=<token>

An iCalendar feed of changelog releases, published and scheduled, with stable UIDs.

← Back to Votera · Manual · Quickstart · Test run

Affiliate program
Recommend tools people own — earn 35% on every sale. 90-day tracking, instant delivery, payouts by Lemon Squeezy.
Become an affiliate →