Skip to content
esc

Search pages and sections. Try a tool name, an error code, a route.

↑↓ navigate↵ openesc close

Guides · Concepts

Keys and identities

Three kinds of keys, two kinds of sessions, and the rules that never change: a key is shown once, a revoked key is refused from the next request on, and a secret key is born only in front of a human.

The three keys#

KeyPrefixHeld byOpensExposable
Account keyak_Your agent (MCP server or remote connector). The dashboard uses its own identifier, never this keyEvery project of the account within its scope — create projects, manage keys, read and write any data, deployNever. It lives in your agent's configuration, never in an app or a repository
Publishable keypk_Your app's front end, in every visitor's browserOne project, through the access presets: a visitor without a session is anon, a signed-in person is userYes, by design. It identifies the project and grants nothing on its own
Secret keysk_Your own server code, if you have someOne project, every right, the access presets do not applyNever in a browser. The SDK refuses it there

An account has at most one live agent key at a time: installing the remote connector revokes the key a local server was using, and vice versa. The Account screen names which one holds it ("Held by").

Two sessions, never interchangeable#

  • X-Session carries an end user of an app: someone who signed up through the app with the publishable key. It comes from the auth routes and lives 30 rolling days, 90 at most.
  • X-Account-Session carries the owner of the account: your own dashboard sign-in. Only an account key reads it; it is what proves that a human is behind a request. It never travels from a browser to the API, and the remote connector has no channel for it. See The human boundary.

Shown once, then hashed#

A key is shown once, at creation, then stored hashed — nobody, not even us, can read it back. Lost a project key? Rotate it. Lost the account key? Revoke it and generate a new one from the Account screen.

Rotation and grace#

Rotating a project key issues a new value and keeps the old one working for 24 hours (grace_until), so a deployment has time to switch. A key is a record with one or two values, each listed with its own id: the newest is active, the previous one is rotating until its grace ends, and a dead value is revoked. Rotating an already rotating key expires the older value immediately; both values share the same 300 requests per minute. revoke_previous: true cuts the previous value at once. Revoking the newest value cuts both; revoking the previous one cuts only that one. The account key has no rotation — revoke, then generate.

Revocation: from the next request on#

A revoked key is refused from the next request on, everywhere, with no grace. An account key is checked against our own records on every request. A publishable or secret key is checked against the key service, then against the list of cut keys kept in the project's own database — the revocation writes it there before it answers, so a 200 means the key is cut. If it cannot write it, the revocation answers 503: the key is revoked at the key service all the same, but may still be accepted for up to 10 minutes — repeat the call until 200. A function's key cut by a redeploy or by rotate_function_secret follows the key service alone, up to 10 minutes; revoke its fn: entry to cut it at once. What it costs: one more read in the project's database on each request carrying a publishable or secret key.

The inert publishable key — removed on 2026-09-07#

A publishable key created by an agent alone used to be inert: it worked for everything except POST /v1/auth/signup, and a human had to issue the active one from the dashboard.

That rule is gone. Every publishable key signs users up, whoever created it. An agent can build the whole backend and enroll its users, with no dashboard visit in between.

The fiche still carries an inert field, always false. It stays only because removing a published field would break /v1; it tells you nothing.

The secret-key frontier#

The value of a secret key — every right on a project — is obtainable only in the dashboard, with a signed-in human. With an account key, so from an agent: listing and revoking secret keys, yes; creating one, rotating it, or reading its value, no (401, human required). This is a real API boundary, not a restriction of the MCP server.

Scope of the account key#

The human who issues an account key chooses what it opens: every project, or a list. Outside its scope, every project route answers the neutral 404. Creating a project requires the "every project" scope. The scope is fixed at issuance; to change it, revoke and generate a new key.

A shared secret is closed to limited keys until you tick the box on the Secrets screen: a function deployed by such a key does not receive it, and the five account-secret routes answer 403 to it — they act on the whole account. While a closed shared secret exists, a limited key is also refused (409) when it would redeploy a function whose script may still carry it.

Naming and emergency stops#

Every project key has a required name (1–64 characters, not unique) — it is what tells you which key to revoke. Revoking a project key needs no human: cutting off a leaked key must not wait. Revoking the account key is done from the Account screen; it is the only key that may be revoked by the very request it authenticates.

The browser identifier#

Each browser you sign in to the dashboard with gets its own identifier, never shown to you, linked to your account and cut when you unlink that browser or sign out. Ten browsers can be linked at once. Browsers are not agents: they do not count towards the one-agent-key rule, and revoking your agent key does not sign any browser out.

Other bearers, and how long they live#

BearerLivesSingle-use
Invitation link7 daysyes
Password-reset link1 houryes — and using it signs the person out everywhere
Confirmation token (428)5 minutesyes
Idempotency key24 hours—
End-user session (X-Session)30 rolling days, 90 at most—
Account session (dashboard)a one-hour token, renewed while the dashboard is open; no absolute limit and no inactivity limit today — signing out ends it—
Remote connector tokens (OAuth)code 10 minutes · access 8 hours · refresh 30 rolling dayscode and refresh yes