API
Errors and rate limits
What each status code means, and how to operate keys — rotation, revocation, leak response.
Errors come back as an HTTP status with a JSON body carrying statusCode and message. The message is written for the person reading the log, not for pattern matching — branch on the status.
What each status means
| Status | Means |
|---|---|
401 | Unknown, revoked or expired key — or presented from outside its IP allowlist. One message for all four, because the differences are exactly what a prober would use to map the key space. |
403 “not available to API keys” | The endpoint is session-only. See what a key can reach. |
403 “missing the … scope” | The endpoint is open; your key lacks the scope. |
403 “restricted to other projects” | The key’s projectIds does not include the project this resource belongs to. |
403 “account … is not active” | The owner was suspended or banned. Their keys stopped on the same request. |
400 “already holds 50 live API keys” | The per-account cap. Revoke one — revoked and expired keys do not count. |
400 | The request body did not validate. The message names the field. |
404 | No such resource — or one you cannot see. The two are not distinguished, for the same reason as the 401. |
429 | Rate limited. Back off and retry; the response carries the usual Retry-After semantics. |
A quota refusal is a
4xx too — a project at its ceiling declines new work explicitly rather than degrading quietly.Operating keys over time
- Rotate by overlap
- Mint the replacement, deploy it, then revoke the old one. Revocation is immediate, so the order matters.
lastUsedAt/lastUsedIp- Stamped at most once a minute per key — stamping every request would turn a read into a write and make a hot CI key contend on its own row. Good enough to answer “is anything still using this?”; not an access log.
- The audit trail
- Records create, revoke and delete with the key’s name, prefix, and the scopes it actually holds — the sanitised set, not what was requested, so a line never shows a grant that was dropped. See audit.
A key has leaked
- 01Revoke it. Immediate, and it keeps the row so the audit trail survives. Deleting also works but destroys the evidence.
- 02Read the audit log for what it did while it was out.
- 03Mint a replacement with narrower scopes if the incident showed the old one was broader than the job needed.
If the key is not yours, any admin with users:manage can revoke it — see stopping a key you do not own. You do not need the holder.
Because a key never exceeds its owner, the blast radius is bounded by that account’s rights. That is the argument for minting keys under a purpose-made account rather than under your own admin login.