v1.0.0

Portal Public API

The public HTTP surface of the Portal platform.

Portal exposes two hosts:

  • https://api.useportal.co — the control plane. Tenant backends call it with a secret key (sk_...) to mint end-user tokens, publish server messages, manage channel membership and bans, send notifications, and deploy configuration. One route (/v1/tokens/anonymous) also accepts a publishable key (pk_...) so a browser can mint anonymous tokens with no backend in the loop.
  • https://realtime.useportal.co — the realtime edge. End-user clients call it with a Portal user JWT (minted via /v1/tokens) to publish messages on their own behalf and to read message history and channel rosters.

Authentication at a glance

  • secretKeyAuthorization: Bearer sk_.... Server-only; never send a secret key from a browser (requests carrying an Origin header are rejected).
  • publishableKeyAuthorization: Bearer pk_... or the x-portal-key: pk_... header. Browser-safe; accepted only on /v1/tokens/anonymous.
  • userTokenAuthorization: Bearer <jwt>. A Portal user JWT minted via /v1/tokens (or /v1/tokens/anonymous for anonymous users). Used on the realtime host.

The environment a credential belongs to is resolved from the credential itself, never from the URL.

Errors

Every non-2xx response has a JSON body { code, reason? } and an x-portal-error response header carrying the same code. Read code from the body or the header rather than branching on HTTP status alone — several codes share a status.

Excluded from this document

The following are deliberately not modeled here:

  • /internal/* — platform-internal surfaces, not callable with customer credentials.
  • Dashboard CRUD routes — Clerk-session-authenticated routes used by the Portal dashboard (organization/project/environment/API-key/allowed-origin management, the message browser, and the logs-token mint's sibling routes). The one dashboard route useful to integrators, POST /v1/environments/{envId}/logs-token, is included and flagged below.
  • WebSocket endpoints (GET /v1/channels/{id}, GET /inbox, GET /v1/environments/{envId}/logs) — OpenAPI does not model WebSockets. They are documented separately as prose, including the connection handshake, frame types, and refusal codes.

Control plane (tenant backend, secret key).

Client Libraries