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.
/v1/projects/:pid/keyslist_keys/v1/projects/:pid/keys { kind, name }create_key201 with the key's value — the only place it ever appears. kind is pk or sk; name is required (1–64 characters)/v1/projects/:pid/keys/:kid/rotate { revoke_previous? }rotate_key201 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)/v1/projects/:pid/keys/:kidrevoke_key503 if the cut could not be recorded — repeat until 200The 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 apk_. (Until 2026-09-07 apk_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. WithoutX-Account-Sessionthe route answers401, 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
201response 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.
| Status | Meaning |
|---|---|
active | the newest value of the key, live |
rotating | the previous value, live until its grace ends |
revoked | a 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.
