Skip to content
esc

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

↑↓ navigate↵ openesc close

API reference · Management plane

Project keys

Issue, list, rotate and revoke the publishable (pk_) and secret (sk_) keys of a project. The account key (ak_) is not a project key and never appears here; it is managed from the Account screen of the dashboard.

Host: https://api.manybases.com · Key: ak_. Some gestures also require a signed-in human (X-Account-Session). The meaning of each key class is in Keys and identities.

GET/v1/projects/:pid/keys
Toollist_keys
EffectThe keys of the project. The value is never returned. Fields are graded on the presence of a signed-in human — see below
POST/v1/projects/:pid/keys { kind, name }
Toolcreate_key
Effect201 with the key's value — the only place it ever appears. kind is pk or sk; name is required (1–64 characters)
POST/v1/projects/:pid/keys/:kid/rotate { revoke_previous? }
Toolrotate_key
Effect201 with the new value. The old one keeps working for 24 hours (grace_until), unless revoke_previous: true, which cuts it at once. A key with no live value cannot be rotated (403)
DELETE/v1/projects/:pid/keys/:kid
Toolrevoke_key
EffectRevoke, with no grace: the key is refused from the next request on, everywhere. 503 if the cut could not be recorded — repeat until 200

The key card#

Base tier, visible to an account key alone: { id, kind, name, created_at, revoked_at, status } with status in active or revoked, plus inert on a pk_ — absent on an sk_. inert is always false since 2026-09-07: it stays only because removing a published field would break /v1, and it tells you nothing.

With a signed-in human: prefix (a truncated form such as sk_demo_…0000), last_used_at, grace_until, the rotating status, and the accountability fields label, created_by, revoked_by, revoked_reason.

Naming#

name is required on creation: absent, empty or whitespace-only → 400 validation_error. It is free-form, 1 to 64 characters, not unique — it is what tells you which key to revoke later ("web app", "staging server"). The prefix fn: is reserved: it is the form that binds a key to an edge function.

Creating#

  • A pk_ can be created by an account key alone, and it signs users up like any other: every publishable key does, whoever created it. An account session that is missing, invalid or expired does not refuse a pk_. (Until 2026-09-07 a pk_ created without a signed-in human was inert: it worked for everything except signing users up. That rule is removed.)
  • Creating an sk_ requires a signed-in human. Without X-Account-Session the route answers 401, and no token is issued. This is a real API boundary, not a restriction of the MCP server: an agent calling HTTP directly gets the same refusal. An agent can list and revoke secret keys; it can never create or rotate one, nor read a value.
  • The 201 response carries the value in clear, once. It is never stored in clear and cannot be read back — not by you, not by us.

Rotating#

A key is a record that carries one or two values. Each value is a line of the list with its own id — the key_id the request log shows.

StatusMeaning
activethe newest value of the key, live
rotatingthe previous value, live until its grace ends
revokeda dead value: revoked, past its grace, or cut by a rotation

Rotation issues a new value and keeps the previous one valid for 24 hours, so a deployment has time to switch — or cuts it at once with revoke_previous: true, the gesture for a key that leaked. The path can name any live value of the key. Rotating a key that is already rotating expires the older of its two values immediately, and a grace never gets longer. The two values share the same 300 requests per minute. Rotating an sk_ requires a signed-in human, like creating one. A value that is no longer live cannot be rotated: 403, and the hint points to the value that replaced it, or to creating a new key. A body that is not a JSON object, or a revoke_previous that is not true or false, answers 400.

An account key has no rotation: an account has at most one live agent key, so "rotating" it means revoking and reissuing from the Account screen, with a cut in between.

Revoking#

Revocation has no grace, unlike rotation: anything still using the key receives 401 from the next request on, everywhere. The cut is recorded in the project's own database before the call answers; if it cannot be, the call answers 503 — the key is revoked at the key service all the same, and may still be accepted for up to 10 minutes: repeat the call until 200, which is safe. A value cut by a rotation is recorded the same way; if an older value cannot be, the rotation answers 503 and issues nothing. Revoking the newest value of a rotating key cuts both of its values; revoking the previous one cuts only that one, and the value that replaced it keeps working. No human is required — cutting off a leaked key must never wait. The three refusals a caller can read afterwards are distinct: "unknown", "revoked" and "replaced by a rotation" carry different hints.

Two hard refusals#

  • The account key is not a project key and is not in this list: mixing them would let a client revoke the key it authenticates with → 403 forbidden.
  • Rotating or revoking the key presented in the current request is refused → 403 forbidden. A click would put the caller out of service.

Rotating a function's key (fn: prefix) through this route is refused too; the gesture is the function's own rotate-secret route. Revoking one is allowed — it is the finest emergency stop the product has.