Authentication
API tokens: one credential per use, scoped to what it needs, and revocable on its own.
API tokens
Anything outside the portal (a script, a monitor, an agent) signs in with an API token. Create one under
Settings → API tokens, and send it in the Authorization header:
Authorization: Bearer zhos_…
A token is only ever read from that header, never from a URL.
The token is shown once, when you create or rotate it. Only a hash of it is stored, so nobody (Zero Human included) can read it back; the list shows its name, its last four characters, and when it was last used.
- Rotate issues a new secret with the same name and scopes, and the old one stops working at once. The replaced token stays listed, revoked, so the record outlives the credential.
- Revoke stops a token at once.
- A token acts for the enterprise it was created in.
Scopes
Every token has at least one scope, and there is no default: a credential's reach is always something someone
chose. A scope is <resource>:<level>:
- the resource is the first part of a route's path after
/v1, soruns:readreads/v1/runs,/v1/runs/{id}and/v1/runs/{id}/log; - the level is
readforGET, andwritefor everything else.writeincludesread.
The resources are blockers, catalog, chats, enterprise, executions, gates, llm, members, memory,
orgs, plans, proposals, recommendations, roles, runs, spend, tasks, teams, tools and webhooks.
Because the resource is the first part of the path, a route nested under a task is a task route:
POST /v1/tasks/{id}/runs (start a run) needs tasks:write, not runs:write.
A route whose first part is not a resource is refused to every token. New parts of the API are closed to tokens until they are given a resource, so a token never gains reach it was not granted.
You can only grant a token scopes you hold yourself.
Two things a scope does not tell you
gates:writereally does decide gates, including approving something going live. Grant it deliberately.- No token can manage tokens, whatever
enterprise:writewould otherwise reach. A token that could create tokens would make revoking one pointless: a leaked one would simply leave a fresh one behind.
When a token is refused
| Status | error |
What it means |
|---|---|---|
401 |
No token, or not one that is valid (unknown, revoked, or rotated away). | |
403 |
api_token_scope |
The token lacks the scope this route needs. The message names it: "This token needs runs:write; it has runs:read." |
403 |
api_token_cannot_manage_tokens |
Token management is only in the portal. |