Docs/API reference

API reference

A REST API over HTTPS with JSON requests and responses. Build anything the product does, on your own data.

Base URL

https://api.sarvafeed.com/v1

Authentication

Authorization: Bearer <token>

Rate limit

120 requests per minute per token. Every response includes X-RateLimit-Remaining.

Versioning

The version is pinned in the path (/v1). Breaking changes ship under a new version, never in place.

Authentication

POST/auth/tokens

Exchange an API key for a short-lived access token. Most requests use the workspace key directly as a bearer token, but service integrations can mint scoped tokens here.

scopes
string[]

Optional list of scopes to restrict the token, e.g. posts:read.

expires_in
integer

Lifetime in seconds. Defaults to 3600, max 86400.

request
curl -X POST https://api.sarvafeed.com/v1/auth/tokens \
  -H "Authorization: Bearer $SARVAFEED_KEY" \
  -d '{ "scopes": ["posts:read","posts:write"], "expires_in": 3600 }'
response
{
  "access_token": "tok_9d2fk3a1",
  "expires_in": 3600,
  "scopes": ["posts:read", "posts:write"]
}

Boards

GET/boards

List every board in your workspace.

response
{
  "data": [
    { "id": "board_2xk9", "name": "Feature Requests", "post_count": 214, "public": true },
    { "id": "board_7pm2", "name": "Bug Reports", "post_count": 58, "public": false }
  ]
}
GET/boards/:id

Retrieve a single board by id.

response
{
  "id": "board_2xk9",
  "name": "Feature Requests",
  "public": true,
  "statuses": ["open", "under_review", "planned", "in_progress", "shipped"],
  "created_at": "2026-01-12T09:20:00Z"
}

Posts

GET/posts

List posts across a board with filters and pagination.

board
string

Board id to scope results to.

status
string

Filter by status, e.g. planned.

sort
string

One of recent, votes, or weighted. weighted ranks by revenue-weighted score.

request
curl "https://api.sarvafeed.com/v1/posts?board=board_2xk9&sort=weighted" \
  -H "Authorization: Bearer $SARVAFEED_KEY"
response
{
  "data": [
    {
      "id": "post_8fk2",
      "title": "SSO for the public portal",
      "status": "planned",
      "vote_count": 42,
      "weighted_score": 18400,
      "created_at": "2026-02-18T14:03:00Z"
    }
  ],
  "next_cursor": "cur_a91k"
}
POST/posts

Create a feedback post on a board.

board_id
stringrequired

Board the post belongs to.

title
stringrequired

Short summary of the request.

body
string

Longer description.

author_email
string

Attribute the post to a user for revenue weighting.

request
curl -X POST https://api.sarvafeed.com/v1/posts \
  -H "Authorization: Bearer $SARVAFEED_KEY" \
  -d '{ "board_id": "board_2xk9", "title": "Dark mode", "author_email": "sam@acme.com" }'
response
{
  "id": "post_5td7",
  "title": "Dark mode",
  "status": "open",
  "vote_count": 1,
  "weighted_score": 240,
  "created_at": "2026-07-05T11:42:00Z"
}
PATCH/posts/:id

Update a post's status, title, or tags. Status changes notify subscribed voters.

status
string

New status, e.g. in_progress.

title
string

Updated title.

tags
string[]

Replace the post's tags.

request
curl -X PATCH https://api.sarvafeed.com/v1/posts/post_8fk2 \
  -H "Authorization: Bearer $SARVAFEED_KEY" \
  -d '{ "status": "in_progress" }'
response
{
  "id": "post_8fk2",
  "status": "in_progress",
  "updated_at": "2026-07-05T12:01:00Z"
}

Votes

POST/posts/:id/votes

Cast a vote on a post. If the voter's account is linked, the vote carries its revenue weight.

voter_email
stringrequired

Identifies the voter and their account.

request
curl -X POST https://api.sarvafeed.com/v1/posts/post_8fk2/votes \
  -H "Authorization: Bearer $SARVAFEED_KEY" \
  -d '{ "voter_email": "lee@acme.com" }'
response
{
  "post_id": "post_8fk2",
  "vote_count": 43,
  "weighted_score": 18640
}
DELETE/posts/:id/votes

Remove a voter's vote from a post.

voter_email
stringrequired

The voter to remove.

response
{
  "post_id": "post_8fk2",
  "vote_count": 42,
  "weighted_score": 18400
}

Statuses

GET/statuses

List the status pipeline configured for your workspace.

response
{
  "data": [
    { "key": "open", "label": "Open", "color": "#6bbfbe" },
    { "key": "under_review", "label": "Under Review", "color": "#e8cf6e" },
    { "key": "planned", "label": "Planned", "color": "#8189f2" },
    { "key": "in_progress", "label": "In Progress", "color": "#8189f2" },
    { "key": "shipped", "label": "Shipped", "color": "#7fb98a" }
  ]
}

Changelog

GET/changelog

List published changelog entries, newest first.

response
{
  "data": [
    {
      "id": "rel_28",
      "version": "v2.8.0",
      "title": "Slack Integration & Real-Time Notifications",
      "tag": "New Feature",
      "published_at": "2026-07-02T00:00:00Z"
    }
  ]
}

Webhooks

Subscribe to events and sarvaFeed posts a signed payload to your endpoint. Verify the signature with the secret returned at registration.

POST/webhooks

Register a webhook endpoint for one or more events.

url
stringrequired

HTTPS endpoint that receives event payloads.

events
string[]required

Events to subscribe to (see the list below).

request
curl -X POST https://api.sarvafeed.com/v1/webhooks \
  -H "Authorization: Bearer $SARVAFEED_KEY" \
  -d '{ "url": "https://acme.com/hooks/sarvafeed", "events": ["post.status_changed"] }'
response
{
  "id": "whk_3a9d",
  "url": "https://acme.com/hooks/sarvafeed",
  "events": ["post.status_changed"],
  "secret": "whsec_1f8k2m"
}
DELETE/webhooks/:id

Delete a registered webhook.

response
{
  "id": "whk_3a9d",
  "deleted": true
}

Events

post.created

A new post lands on a board.

post.status_changed

A post moves to a new status.

post.vote_milestone

A post crosses a vote threshold you configured.

changelog.published

A changelog entry goes live.

Errors

Errors return the matching HTTP status and a JSON body with a stable machine-readable code.

response
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid bearer token."
  }
}
400bad_request

The request body or query was malformed.

401unauthorized

Missing or invalid bearer token.

403forbidden

The token lacks the scope for this action.

404not_found

The resource does not exist.

429rate_limited

You exceeded 120 requests per minute. Retry after the window resets.