REST management API ยท v1

Build customer feedback into your workflow.

Plain text, including every endpoint and example below.

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

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.
MethodPathPurposeMCP tool
GET/api/v1/projectsList projects available to the project-bound API key.list_projects
GET/api/v1/projects/:projectId/featuresList and cursor-page feature requests.list_features
POST/api/v1/projects/:projectId/featuresCreate a request in the default or supplied status.create_feature
GET/api/v1/projects/:projectId/features/:featureIdRead one feature request.get_feature
PATCH/api/v1/projects/:projectId/features/:featureIdEdit, moderate, or change request status and follower policy.update_feature
DELETE/api/v1/projects/:projectId/features/:featureIdSoft-delete a request.delete_feature
GET/api/v1/projects/:projectId/features/:featureId/commentsList non-deleted comments with moderation state.list_comments
POST/api/v1/projects/:projectId/features/:featureId/commentsAdd an administrative comment.create_comment
GET/api/v1/projects/:projectId/releasesList draft, scheduled, and published releases.list_releases
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
GET/api/v1/projects/:projectId/usageReturn project counters and plan usage.project_usage
GET/api/featuresSource-compatible page list with status, tag, and search filters; project comes only from the key.compatibility_list_features
POST/api/features/createCreate a feature using source field names without accepting author identity or a project override.compatibility_create_feature
GET/api/features?featureId=:featureIdRead one project-bound feature using source field names.compatibility_get_feature
PUT/api/featuresUpdate feature title, description, or tags transactionally.compatibility_update_feature
PUT/api/features?is_status_update=trueUpdate feature status through the notification-policy-aware transaction.compatibility_update_feature_status
DELETE/api/featuresSoft-delete one feature bound to the key project.compatibility_delete_feature
GET/api/features/voters?featureId=:featureIdList safe voter labels and masked email only; raw identity data is never returned.compatibility_list_voters
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
GET/api/comments?featureId=:featureIdPage administrative comments without actor identities.compatibility_list_comments
POST/api/comments/create?featureId=:featureIdCreate a public administrative comment or a private internal note.compatibility_create_comment
PUT/api/commentsUpdate comment body or internal visibility within the key project.compatibility_update_comment
DELETE/api/commentsRetention-bound soft deletion of one project comment.compatibility_delete_comment
GET/api/releasesPage project-bound releases using the source version, description, feature, and draft fields.compatibility_list_releases
GET/api/releases?releaseId=:releaseIdRead one project-bound release using the source release fields.compatibility_get_release
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
PUT/api/releasesUpdate source release fields and replace feature links within the key project. Setting is_draft to false additionally requires releases:publish.compatibility_update_release
DELETE/api/releases?releaseId=:releaseIdRetention-bound soft deletion of one project release.compatibility_delete_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
GET/api/projectsReturn the single project, statuses, and tags bound to the API key.compatibility_get_project
GET/api/usageReturn source-named aggregate project counters; features and featureRequests currently share the same non-deleted count.compatibility_get_usage

Request and response examples

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

GET/api/v1/projectsprojects:read

Request

GET /api/v1/projects
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "projects": [
      {
        "id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
        "name": "Northstar",
        "slug": "northstar",
        "description": "Customer feedback for the Northstar product.",
        "visibility": "public",
        "published_at": "2026-07-13T12:00:00.000Z",
        "archived_at": null,
        "created_at": "2026-07-13T12:00:00.000Z",
        "updated_at": "2026-07-13T12:00:00.000Z"
      }
    ]
  }
}
GET/api/v1/projects/:projectId/featuresfeatures:read

Request

GET /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/features?limit=50&cursor=NEXT_CURSOR
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "features": [
      {
        "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"
      }
    ],
    "nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LS4uLiJ9"
  }
}
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"
    }
  }
}
GET/api/v1/projects/:projectId/features/:featureIdfeatures:read

Request

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

Success response

200 OK

{
  "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"
    }
  }
}
PATCH/api/v1/projects/:projectId/features/:featureIdfeatures:write

Request

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

{
  "statusId": "97a8ad23-f482-49bb-88b9-716c5f41709d",
  "notifyFollowers": false
}

Success response

200 OK

{
  "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": false,
      "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"
    }
  }
}
DELETE/api/v1/projects/:projectId/features/:featureIdfeatures:write

Request

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

Success response

204 No Content

(no response body)
GET/api/v1/projects/:projectId/features/:featureId/commentscomments:read

Request

GET /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/features/f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f/comments?limit=50
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "comments": [
      {
        "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"
      }
    ],
    "nextCursor": null
  }
}
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"
    }
  }
}
GET/api/v1/projects/:projectId/releasesreleases:read

Request

GET /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/releases?limit=50
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "releases": [
      {
        "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"
      }
    ],
    "nextCursor": null
  }
}
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"
    }
  }
}
GET/api/v1/projects/:projectId/usageusage:read

Request

GET /api/v1/projects/3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2/usage
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "projectId": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
    "counts": {
      "features": 42,
      "votes": 318,
      "comments": 67,
      "releases": 8,
      "activeSubscribers": 96
    },
    "calculatedAt": "2026-07-13T12:00:00.000Z"
  }
}
GET/api/featuresCompatibility aliasfeatures:read

Request

GET /api/features?page=1&limit=50&status=In%20progress&tag=Mobile&search=native
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "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"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 1
  }
}
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"
  }
}
GET/api/features?featureId=:featureIdCompatibility aliasfeatures:read

Request

GET /api/features?featureId=f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "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"
  }
}
PUT/api/featuresCompatibility aliasfeatures:write

Request

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

{
  "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
  "description": "Beta access for field teams",
  "tags": [
    "Mobile",
    "Beta"
  ]
}

Success response

200 OK

{
  "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"
  }
}
PUT/api/features?is_status_update=trueCompatibility aliasfeatures:write

Request

PUT /api/features?is_status_update=true
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
  "status": "In progress"
}

Success response

200 OK

{
  "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"
  }
}
DELETE/api/featuresCompatibility aliasfeatures:write

Request

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

{
  "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f"
}

Success response

200 OK

{
  "data": {
    "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
    "deleted": true
  }
}
GET/api/features/voters?featureId=:featureIdCompatibility aliasfeatures:read

Request

GET /api/features/voters?featureId=f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f&page=1&limit=25
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": [
    {
      "label": "Email subscriber",
      "masked_email": "a***e@e*****e.com",
      "identity_kind": "subscriber",
      "status": "active",
      "created_at": "2026-07-13T12:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 25,
    "total": 1
  }
}
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
  }
}
GET/api/comments?featureId=:featureIdCompatibility aliascomments:read

Request

GET /api/comments?featureId=f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f&page=1&limit=50
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": [
    {
      "id": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
      "featureId": "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f",
      "body": "We have started the technical design.",
      "is_internal": false,
      "moderation_state": "visible",
      "createdAt": "2026-07-13T12:00:00.000Z",
      "updatedAt": "2026-07-13T12:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 1
  }
}
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"
  }
}
PUT/api/commentsCompatibility aliascomments:write

Request

PUT /api/comments
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "commentId": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
  "body": "Updated internal triage note",
  "is_internal": true
}

Success response

200 OK

{
  "data": {
    "id": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
    "is_internal": true
  }
}
DELETE/api/commentsCompatibility aliascomments:write

Request

DELETE /api/comments
Authorization: Bearer ps_live_your_key
Accept: application/json
Content-Type: application/json

{
  "commentId": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816"
}

Success response

200 OK

{
  "data": {
    "commentId": "25bb8fa2-1eec-47a5-9f45-4400dcc9e816",
    "deleted": true
  }
}
GET/api/releasesCompatibility aliasreleases:read

Request

GET /api/releases?page=1&limit=50
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "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"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 1
  }
}
GET/api/releases?releaseId=:releaseIdCompatibility aliasreleases:read

Request

GET /api/releases?releaseId=b6f1472f-2fc3-4dd9-b06e-c8931ae245f7
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "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/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"
  }
}
PUT/api/releasesCompatibility aliasreleases:write

Request

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

{
  "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
  "short_description": "The customer beta is ready.",
  "feature_ids": [
    "f5b5c8e1-cff5-4c3f-98ec-f951dc437e2f"
  ],
  "is_draft": false
}

Success response

200 OK

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

Request

DELETE /api/releases?releaseId=b6f1472f-2fc3-4dd9-b06e-c8931ae245f7
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "releaseId": "b6f1472f-2fc3-4dd9-b06e-c8931ae245f7",
    "deleted": true
  }
}
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
}
GET/api/projectsCompatibility aliasprojects:read

Request

GET /api/projects
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "id": "3fc4d742-57ef-4d41-b22e-c0bdb43a0fd2",
    "name": "Northstar",
    "slug": "northstar",
    "description": "Customer feedback for Northstar.",
    "visibility": "public",
    "statuses": [
      {
        "id": "97a8ad23-f482-49bb-88b9-716c5f41709d",
        "name": "In progress",
        "slug": "in-progress"
      }
    ],
    "tags": [
      {
        "id": "79d40fa1-cd6e-4018-8011-bd1af83f29ec",
        "name": "Mobile",
        "slug": "mobile"
      }
    ]
  }
}
GET/api/usageCompatibility aliasusage:read

Request

GET /api/usage
Authorization: Bearer ps_live_your_key
Accept: application/json

Success response

200 OK

{
  "data": {
    "upvotes": 318,
    "featureRequests": 42,
    "views": 1280,
    "features": 42,
    "releases": 8
  }
}
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..."
  }
}