Skip to main content
One hostname does not mean one credential. Each class exists for one job and can never do another’s.

API keys

The Authorization header value is Bearer <api-key>. Replace <api-key> with your key; the angle brackets are placeholder notation, not part of it. Send the key as Authorization: Bearer sempera_sk_.... No other header or scheme is recognised; a key on any route outside /v1 is ignored. A key has:
  • a workspace: the one customer account it lives in;
  • a role: owner, operator or viewer, the same ladder a person has in the workspace. A key is never minted above the role of whoever minted it, and each kind has a ceiling (a runtime or CI key is at most a viewer);
  • scopes: an explicit list. Each route names the scope it needs; a key without it gets 403 insufficient_scope before anything runs. kind caps which scopes a key may hold at all.
Scopes: agents:read, agents:write, agents:publish, sessions:read, sessions:write, calls:read, calls:write, phone_numbers:read, phone_numbers:write, tools:read, tools:write, tools:execute, integrations:read, integrations:write, knowledge:read, knowledge:write, tests:read, tests:write, evals:read, evals:write, workspaces:read, workspaces:write, organizations:read, api_keys:read, api_keys:write, webhooks:read, webhooks:write, deploy:read, models:read, prompts:read, prompts:write, phone:read, phone:call, phone:text. Authorization is two locks: the scope (what the credential was minted for) and the role (what that identity may do to the resource). Both must pass. Default is deny.

Minting and revoking

A workspace owner creates keys in the Sempera App under Settings, API keys, or with POST /v1/api-keys (owner only, api_keys:write); either way the secret is shown once. The first key of a workspace is created in the App, because creating a key needs an owner’s signed-in session or an admin key, and a developer key can never mint keys. GET /v1/api-keys lists keys without secrets. DELETE /v1/api-keys/{id} revokes immediately. GET /v1/me describes the calling credential.

Connected clients

Each outside client gets its own grant, so one can be ended without touching another. An owner sees them all in Settings, Connected clients, with scopes and last use. OAuth, for MCP hosts. The host discovers the door from the 401 on POST /v1/mcp, registers itself, and sends the browser to a consent page on app.sempera.org. Only a signed-in workspace owner can approve, and no key or token can do it for them. The grant covers one client in one workspace with the scopes approved there, and approving the same client again replaces it. The flow is authorization code with PKCE (S256), exact redirects and audience binding to https://api.sempera.org/v1/mcp. Details are in MCP. A scoped REST credential, for a client that cannot do OAuth. An owner creates one in Settings, Connected clients, or with POST /v1/client-grants/rest (client, scopes, optional expires_in_days). It holds phone scopes only, works on the phone routes only, expires in 90 days by default (at most 365), and is shown once. GET /v1/client-grants lists every connected client (OAuth, MCP keys and REST credentials) and DELETE /v1/client-grants/{grant_id} ends one. An ordinary API key, another workspace’s client and an unknown id all read as not_found.

Browser clients

A browser never holds an API key. Your server calls POST /v1/sessions and hands the browser the returned token and url; the token is scoped to one room and expires with the conversation.

Sign-in for people

People sign in to the Sempera App with Google, Apple, email or phone. Those roads live on app.sempera.org and never on the API.