Skip to content
Browse this documentation8 sections

REST management API · v1

Build customer feedback into your workflow.

Manage projects, requests, comments, releases, and usage from server-side tools. The API uses JSON, scoped project keys, cursor pagination, and predictable error envelopes.

Plain text, including 12 matching endpoints and examples below.
Admin use only — not for public-facing UIs. API keys grant management privileges. Never expose one in client-side code, browser storage, a public website, or a URL.

Scoped keys

Grant only the read or write scopes an integration needs.

Rate limited

Standard limits are 100 requests per minute per key.

Privacy safe

Private actor traits and subscriber addresses are never returned.

curl https://priosmith.com/api/v1/projects \
  -H "Authorization: Bearer ps_live_your_key" \
  -H "Accept: application/json"
01

Authentication

Send a project-bound API key as a Bearer token. Keys are shown once when created, then stored only as a purpose-separated HMAC digest. Rotate a key immediately if it is exposed.

Authorization: Bearer ps_live_your_key
ScopeAllows
projects:readList accessible projects and configuration
features:read / features:writeRead or manage requests and moderation status
comments:read / comments:writeRead or add administrative comments
releases:read / releases:writeRead releases and create drafts
releases:publishPublish a release and enqueue subscriber notifications
usage:readRead aggregate project usage
02

Endpoints

Compatibility privacy differences. Source-compatible voter reads return safe labels and masked email only. Adding a voter queues a confirmation invitation and does not create a vote or consent until the recipient confirms. Author identity fields and caller-supplied project IDs are rejected.

12 of 35 endpoints

Clear endpoint filters
MethodPathPurposeMCP tool
POST/api/v1/projects/:projectId/featuresCreate a request in the default or supplied status.create_feature
POST/api/v1/projects/:projectId/features/:featureId/commentsAdd an administrative comment.create_comment
POST/api/v1/projects/:projectId/releasesCreate a draft or scheduled release. Scheduling additionally requires releases:publish.create_release
POST/api/v1/projects/:projectId/releases/:releaseId/publishPublish a release and queue notifications.publish_release
POST/api/features/createCreate a feature using source field names without accepting author identity or a project override.compatibility_create_feature
POST/api/features/add-voterQueue a confirmation invitation; no vote or consent is created until the recipient confirms.compatibility_add_voter
POST/api/features/link-to-releaseAtomically link one project feature to one project release.compatibility_link_feature_to_release
POST/api/features/mergeTransactionally move votes, subscribers, comments, tags, and release links, then soft-delete the source.compatibility_merge_features
POST/api/comments/create?featureId=:featureIdCreate a public administrative comment or a private internal note.compatibility_create_comment
POST/api/releasesCreate a draft or published release with the source field names. Setting is_draft to false additionally requires releases:publish.compatibility_create_release
POST/api/releases/send-changelog-emailIdempotently queue one consent-safe release email batch for at most 50 confirmed subscribers; recipient identities are never accepted or returned.compatibility_send_changelog_email
POST/api/releases/generate-changelogGenerate customer-facing Markdown from one project release and its linked requests; each attempted provider generation consumes the five-per-project UTC-day quota.compatibility_generate_changelog

Request and response examples

Open an endpoint only when you need its complete example. Copying the documentation includes every matching collapsed example.

POST/api/v1/projects/:projectId/featuresfeatures:write

Request

POST /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/features
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "title": "Native mobile app",
  "body": "iOS and Android access for field teams",
  "postType": "feature"
}

Success response

201 Created

{
  "data": {
    "feature": {
      "id": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
      "request_number": 42,
      "project_id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
      "status_id": "97a8ad23-f482-49bb-88b9-716c5f41709d",
      "title": "Native mobile app",
      "slug": "native-mobile-app",
      "body": "iOS and Android access for field teams",
      "post_type": "feature",
      "moderation_state": "visible",
      "is_pinned": false,
      "notify_followers": true,
      "vote_count": 18,
      "comment_count": 3,
      "subscriber_count": 12,
      "target_date": "2026-10-15",
      "published_at": "2026-07-13T12:00:00.000Z",
      "released_at": null,
      "created_at": "2026-07-13T12:00:00.000Z",
      "updated_at": "2026-07-13T12:00:00.000Z"
    }
  }
}
POST/api/v1/projects/:projectId/features/:featureId/commentscomments:write

Request

POST /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/features/f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f/comments
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "body": "We have started the technical design."
}

Success response

201 Created

{
  "data": {
    "comment": {
      "id": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
      "project_id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
      "post_id": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
      "parent_comment_id": null,
      "body": "We have started the technical design.",
      "is_internal": false,
      "moderation_state": "visible",
      "edited_at": null,
      "created_at": "2026-07-13T12:00:00.000Z",
      "updated_at": "2026-07-13T12:00:00.000Z"
    }
  }
}
POST/api/v1/projects/:projectId/releasesreleases:write

Request

POST /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/releases
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "title": "Mobile beta",
  "slug": "mobile-beta",
  "summary": "The private beta is ready.",
  "status": "draft"
}

Success response

201 Created

{
  "data": {
    "release": {
      "id": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
      "project_id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
      "title": "Mobile beta",
      "slug": "mobile-beta",
      "summary": "The private beta is ready.",
      "body": "Invitations are rolling out to the first customer cohort.",
      "status": "draft",
      "scheduled_at": null,
      "published_at": null,
      "created_at": "2026-07-13T12:00:00.000Z",
      "updated_at": "2026-07-13T12:00:00.000Z"
    }
  }
}
POST/api/v1/projects/:projectId/releases/:releaseId/publishreleases:publish

Request

POST /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/releases/b6f1472f-2fc3-4dd9-b06e-c8931ae245f7/publish
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "release": {
      "id": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
      "project_id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
      "title": "Mobile beta",
      "slug": "mobile-beta",
      "summary": "The private beta is ready.",
      "body": "Invitations are rolling out to the first customer cohort.",
      "status": "published",
      "scheduled_at": null,
      "published_at": "2026-07-13T12:00:00.000Z",
      "created_at": "2026-07-13T12:00:00.000Z",
      "updated_at": "2026-07-13T12:00:00.000Z"
    }
  }
}
POST/api/features/createCompatibility aliasfeatures:write

Request

POST /api/features/create
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "title": "Native mobile app",
  "description": "iOS and Android access for field teams",
  "status": "In progress",
  "tags": [
    "Mobile"
  ]
}

Success response

201 Created

{
  "data": {
    "id": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "title": "Native mobile app",
    "description": "iOS and Android access for field teams",
    "status": "In progress",
    "tags": [
      "Mobile"
    ],
    "votes": 18,
    "createdAt": "2026-07-13T12:00:00.000Z",
    "updatedAt": "2026-07-13T12:00:00.000Z"
  }
}
POST/api/features/add-voterCompatibility aliasfeatures:write

Request

POST /api/features/add-voter
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
  "email": "alex@example.com"
}

Success response

202 Accepted

{
  "data": {
    "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "status": "pending_confirmation",
    "queued": true,
    "confirmation_required": true,
    "masked_email": "a***x@e*****e.com"
  }
}
POST/api/features/link-to-releaseCompatibility aliasreleases:write + features:write

Request

POST /api/features/link-to-release
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
  "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7"
}

Success response

200 OK

{
  "data": {
    "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
    "linked": true
  }
}
POST/api/features/mergeCompatibility aliasfeatures:write

Request

POST /api/features/merge
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "sourceFeatureId": "4d239ed7-c89b-4b22-9cc6-54485336ca58",
  "targetFeatureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f"
}

Success response

200 OK

{
  "data": {
    "sourcePostId": "4d239ed7-c89b-4b22-9cc6-54485336ca58",
    "targetPostId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "merged": true,
    "idempotent": false
  }
}
POST/api/comments/create?featureId=:featureIdCompatibility aliascomments:write

Request

POST /api/comments/create?featureId=f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "body": "Internal triage note",
  "is_internal": true
}

Success response

201 Created

{
  "data": {
    "id": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
    "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "body": "Internal triage note",
    "is_internal": true,
    "moderation_state": "visible",
    "createdAt": "2026-07-13T12:00:00.000Z",
    "updatedAt": "2026-07-13T12:00:00.000Z"
  }
}
POST/api/releasesCompatibility aliasreleases:write

Request

POST /api/releases
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "version": "v1.7.0",
  "title": "Mobile beta",
  "short_description": "The private beta is ready.",
  "long_description": "Invitations are rolling out to the first customer cohort.",
  "feature_ids": [
    "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f"
  ],
  "is_draft": true
}

Success response

201 Created

{
  "data": {
    "id": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
    "version": "v1.7.0",
    "title": "Mobile beta",
    "short_description": "The private beta is ready.",
    "long_description": "Invitations are rolling out to the first customer cohort.",
    "feature_ids": [
      "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f"
    ],
    "is_draft": true,
    "created_at": "2026-07-13T12:00:00.000Z",
    "updated_at": "2026-07-13T12:00:00.000Z"
  }
}
POST/api/releases/send-changelog-emailCompatibility aliasreleases:publish

Request

POST /api/releases/send-changelog-email
Authorization: Bearer ps_live_your_key
Accept: application/json
Idempotency-Key: release-email:request-0001
Content-Type: application/json

{
  "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
  "subject": "Mobile beta is ready",
  "body": "The private beta is now available."
}

Success response

202 Accepted

{
  "data": {
    "batchId": "2d84a58e-a9be-4d4b-b090-1bfd764d6219",
    "status": "queued",
    "recipientCount": 50
  }
}
POST/api/releases/generate-changelogCompatibility aliasreleases:write

Request

POST /api/releases/generate-changelog
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
  "customPrompt": "Write in a friendly tone",
  "existingChangelog": "Optional existing text to improve"
}

Success response

200 OK

{
  "changelog": "# v1.7.0 - Mobile beta\n\n## New features\n\n- The private mobile beta is ready for its first customer cohort.",
  "remaining": 4,
  "limit": 5
}
03

Pagination

Collection endpoints return a stable opaque cursor. Pass the previous response's nextCursor value in the next request. The default page size is 50 and the maximum is 100.

GET /api/v1/projects/PROJECT_ID/features?limit=50&cursor=NEXT_CURSOR

{
  "data": {
    "features": [...],
    "nextCursor": "opaque-value"
  }
}
04

Rate limits

Keys allow 100 requests per minute. Write endpoints also apply a limit of 10 requests per two minutes per key. Counters are coordinated in Supabase across Vercel instances. Every response includes limit, remaining, and reset headers. A 429 response includes Retry-After.

RateLimit-Limit: 100
RateLimit-Remaining: 97
RateLimit-Reset: 1752339660
05

Signed webhooks

Webhook payloads are signed with HMAC-SHA256. Verify the raw request body before parsing JSON, reject stale timestamps, and make event processing idempotent by event ID.

feature.createdfeature.upvotedcomment.createdfeature.status_changedrelease.published
X-PrioSmith-Signature: t=1752339600,v1=hex_digest
X-PrioSmith-Event: feature.status_changed
X-PrioSmith-Delivery: 019f...

{
  "apiVersion": "2026-07-13",
  "id": "019f...",
  "type": "feature.status_changed",
  "createdAt": "2026-07-13T12:00:00.000Z",
  "workspaceId": "WORKSPACE_ID",
  "projectId": "PROJECT_ID",
  "data": { "objectType": "feature", "objectId": "FEATURE_ID" }
}
06

MCP integrations

Streamable HTTP

Connect an MCP client to https://priosmith.com/api/mcp and send the same scoped API key as a Bearer token. The server supports initialization, ping, tool discovery, all twelve canonical management operations, and twenty-three collision-safe compatibility_ tools for the directly evidenced feature, voter, comment, release, project, usage, and changelog-generation operations above. Compatibility tools inherit the key's project boundary and do not accept a project override. Only tools allowed by every required key scope are advertised.

{
  "mcpServers": {
    "priosmith": {
      "url": "https://priosmith.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ps_live_your_key"
      }
    }
  }
}

The transport uses JSON responses without server-managed sessions or SSE. Never put an API key in browser code, a public repository, or a URL.

Stdio package

The repository includes the original-branded @priosmith/mcp-server package source. It forwards newline-delimited JSON-RPC from stdio to the same scoped /api/mcp service without printing credentials.

{
  "mcpServers": {
    "priosmith": {
      "command": "node",
      "args": [
        "/absolute/path/to/priosmith/packages/priosmith-mcp/bin/priosmith-mcp.mjs"
      ],
      "env": {
        "PRIOSMITH_API_KEY": "ps_live_your_key",
        "PRIOSMITH_API_URL": "https://priosmith.com/api/mcp"
      }
    }
  }
}
Registry publication is not verified. The package can be run from this checkout. Do not use npx @priosmith/mcp-server until an owner publishes and verifies the package on npm.
07

Errors

Errors use stable machine-readable codes. A request ID is safe to share with support; raw payloads, credentials, and customer PII are never included.

{
  "error": {
    "code": "BAD_REQUEST",
    "message": "The request is invalid.",
    "requestId": "req_019f..."
  }
}