quickstart
Every example assumes you have an api key (see authentication) and jq for pretty output. Replace spk_<your_key> and the resource ids with values from your org.
The base url is https://api.spirby.com for production. On staging, swap in https://api-staging.spirby.com.
set up shell variables
Section titled “set up shell variables”export SPIRBY_KEY="spk_<your_key>"export SPIRBY_BASE="https://api.spirby.com"The rest of the page uses these.
1. list boards
Section titled “1. list boards”curl -s "$SPIRBY_BASE/v1/boards" \ -H "Authorization: Bearer $SPIRBY_KEY" | jqReturns { "data": [Board, ...], "nextCursor": "..." | null }. Default page size is 25, max 50. Pass ?cursor=...&limit=... for the next page.
2. create a board
Section titled “2. create a board”curl -s -X POST "$SPIRBY_BASE/v1/boards" \ -H "Authorization: Bearer $SPIRBY_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Feedback","description":"What should we build?"}' | jqReturns 201 with { "data": Board } and a Location: /api/v1/boards/<id> header. Slug is derived from the name unless you pass one.
3. get a single board
Section titled “3. get a single board”curl -s "$SPIRBY_BASE/v1/boards/$BOARD_ID" \ -H "Authorization: Bearer $SPIRBY_KEY" | jq4. list posts on a board (with filters)
Section titled “4. list posts on a board (with filters)”curl -s "$SPIRBY_BASE/v1/boards/$BOARD_ID/posts?status=open&sort=most_voted&limit=10" \ -H "Authorization: Bearer $SPIRBY_KEY" | jqFilters: status (single or repeated), tagIds (match-any), query (full-text), sort (most_voted | newest | recently_active | relevance). relevance falls back to most_voted when no query is set. Pagination via cursor + limit (max 50).
5. create a post
Section titled “5. create a post”curl -s -X POST "$SPIRBY_BASE/v1/boards/$BOARD_ID/posts" \ -H "Authorization: Bearer $SPIRBY_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Add csv export", "body": { "json": null, "text": "We need to download the post list as a spreadsheet." } }' | jqReturns 201 with the new post. The author is whichever user minted the api key.
6. read a post (with tags + merge metadata)
Section titled “6. read a post (with tags + merge metadata)”curl -s "$SPIRBY_BASE/v1/posts/$POST_ID" \ -H "Authorization: Bearer $SPIRBY_KEY" | jqThe response includes tags, mergedIntoSlug (if this post was merged into another), and shippedInEntry (if a changelog entry references it).
7. change a post’s status
Section titled “7. change a post’s status”curl -s -X PATCH "$SPIRBY_BASE/v1/posts/$POST_ID" \ -H "Authorization: Bearer $SPIRBY_KEY" \ -H "Content-Type: application/json" \ -d '{"status":"in_progress"}' | jqA status change enqueues a notification job for subscribers; the api response does not wait on the queue. Requires read:write scope.
8. cast a vote (idempotent)
Section titled “8. cast a vote (idempotent)”curl -s -X POST "$SPIRBY_BASE/v1/posts/$POST_ID/votes" \ -H "Authorization: Bearer $SPIRBY_KEY" | jqReturns { "data": { "voted": true, "voteCount": <int> } }. Calling it again with the same key is a no-op — the response shape is identical.
To retract: curl -X DELETE "$SPIRBY_BASE/v1/posts/$POST_ID/votes" -H "Authorization: Bearer $SPIRBY_KEY".
9. comment on a post
Section titled “9. comment on a post”curl -s -X POST "$SPIRBY_BASE/v1/posts/$POST_ID/comments" \ -H "Authorization: Bearer $SPIRBY_KEY" \ -H "Content-Type: application/json" \ -d '{ "body": { "json": null, "text": "Sounds great. Counting on this for q2." } }' | jqPass parentId for one-level replies. Comments are rate-limited per ip (30/h) and per user (60/h) — these limits are separate from the per-key budget.
10. publish a changelog entry (action endpoint)
Section titled “10. publish a changelog entry (action endpoint)”curl -s -X POST "$SPIRBY_BASE/v1/changelog/$ENTRY_ID/publish" \ -H "Authorization: Bearer $SPIRBY_KEY" | jqThe entry must already exist (POST /v1/boards/{boardId}/changelog). Publishing flips status to published, sets publishedAt = now, and enqueues a subscriber broadcast. The endpoint is idempotent — replaying it on an already-published entry is a no-op.
what next
Section titled “what next”- want the rest of the surface? see /api/reference — the browseable spec — or grab openapi.json.
- shipping a webhook receiver? jump to webhooks for payload shapes and signature verification.