ProductOSDocs

API

Authentication

How to authenticate against the ProductOS REST API: the in-app session for browser code, API tokens for everything else.

Every endpoint under /api/v1/* is workspace-scoped and requires authentication. ProductOS supports three auth paths, all of which resolve to the same user, workspace and role:

  1. Session cookie: set automatically by the in-app login flow (/login). Used by the browser, no extra config.
  2. Supabase JWT: in-app code already holds a session; external scripts use an API token.
  3. API token: long-lived pos_live_* token issued from Settings → API Tokens. Best for third-party tools, CI jobs, and external automations.

Which workspace. An API token belongs to the workspace it was issued in and always acts there; to script another workspace, issue a token in it. A browser session acts in the workspace of the page making the request (the app sends it in the x-productos-workspace header); a request that names a workspace you don't belong to, or none, acts in the one you used last.

Picking a method

CallerRecommended auth
Browser, in-app codeSession cookie (automatic)
Internal script, even one run by a signed-in personAPI token (a script has no browser session)
External tool, CI, customer-built integrationAPI token
Your product sending feedback or NPS scores from a serverFeedback API secret key (sk_live_), see Feedback API
Your product sending feedback from the browserPublishable key (pk_live_), same as the widget
Inbound provider webhooksProvider HMAC (verified by ProductOS, you don't send a bearer)

Using an API token

  1. Open Settings → API Tokens.
  2. Click New token (issuing tokens needs the admin or owner role). Pick a name (e.g. "n8n production") and the role the token should act as (defaults to commenter; capped at your own role). An expiry can be set when issuing through the API (expires_at); the dialog issues non-expiring tokens.
  3. Copy the pos_live_xxxxxxxxxxxxx string. This is the only time it's shown: store it in your secret manager immediately.

Send it as a bearer header:

curl 'https://productos.ca/api/v1/feedback?limit=10' \
  -H "Authorization: Bearer pos_live_xxxxxxxxxxxxx"

There is only one API token prefix, pos_live_. ProductOS does not have a sandbox / test-key environment. (Feedback intake keys, sk_live_ and pk_live_, are a separate, narrower kind: they can only submit feedback. See Feedback API.)

Capability is role-based, not scope-based

Tokens carry two things:

  • A coarse scope set (read, write, admin), defaults to ["read", "write"]. Scopes are recorded on the token; what a request may do is decided by role.
  • A role at issuance (viewer | commenter | member | admin | owner), defaults to commenter.

The effective role is the more restrictive of:

  • The token's stored role
  • The token owner's current workspace role

The REST API and the MCP endpoint both check this on every request, so a token never outranks its owner, and a token whose owner has left the workspace stops working. ProductOS also revokes any token that outranks its owner the moment a role is lowered, and every token when the owner leaves.

There are no per-entity scope strings like feedback:read or features:write. The model is the workspace role matrix.

Webhook authentication

  • Outbound webhooks from ProductOS are limited to outbound webhook providers (Slack, Microsoft Teams, Discord, Zapier, Make, n8n) configured under Settings → Integrations. Each posts to the URL you provided. There is no general-purpose outbound-webhook signature scheme; the planned design is in Webhooks.
  • Inbound provider webhooks (GitHub, Linear, etc.) are signed by their respective providers and verified by ProductOS using each provider's documented scheme. You never authenticate inbound integrations with a bearer.

Common errors

CodeMeaningFix
401 unauthorizedMissing, expired, or malformed tokenRe-fetch the token; verify the Bearer prefix; confirm the token wasn't revoked or auto-revoked by a role change
403 forbiddenToken owner's role lacks the required capabilityRe-issue from a higher-role user or have an admin promote the owner
404 not_foundResource doesn't exist or token's workspace doesn't have accessVerify the ID; confirm the token is for the right workspace
429 rate_limitedToo many requests in the rate-limit windowBack off; respect retryAfterSeconds in the response body

Next

Last reviewed 2026-09-22