# API tokens Two token kinds decide execution (ADR 0027 §1); the client — CLI, MCP, raw HTTP — is irrelevant. | kind | TR | execution | |---|---|---| | `agent` | Ajan | **propose-only**: every live mutation is recorded into a [proposal](/reference/proposals); bound to exactly one [workspace](/agents-workspaces) (writing `main` is refused with `agent_workspace_only`); can never apply, publish, or hold secret/token-admin scopes | | `developer` | Geliştirici | **direct**: executes with rev-guarded CAS semantics (409 on drift, never merged) | ## Scope model `scope_registry.grantable_to ∈ {any, developer, session}`; `GET /v1/scopes` serves the registry with TR labels and sensitivity. A token holds at most 10 scopes. Session-only — never mintable on ANY token (the `admin` wildcard included): | scope | |---| | `admin` | | `agents:admin` | | `proposals:approve` | | `checkout` | Ajan-forbidden — an agent token can never be minted with these: | scope | |---| | `admin` | | `agents:admin` | | `proposals:approve` | | `checkout` | | `secrets:write` | | `design:publish` | Defaults at mint: Ajan = `catalog:read`, `design:read`, `catalog:write`, `design:write`, `proposals:write`, `sandbox:use`; Geliştirici = `catalog:read`, `design:read`, `catalog:write`, `design:write`. `orders:*` is opt-in on both (sensitive). Owner-policy commands a **developer** token may still run with an explicit opt-in grant (never in defaults; the mint dialog warns): | command | required scope | |---|---| | [`design.publish`](/reference/commands/design.publish) | `design:publish` | | [`design.rollback`](/reference/commands/design.rollback) | `design:publish` | | [`secret.set`](/reference/commands/secret.set) | `secrets:write` | | [`secret.delete`](/reference/commands/secret.delete) | `secrets:write` | **Secrets can NEVER be set by agents.** `secret.set`/`secret.delete` are owner-policy commands; `secrets:write` is developer-grantable only, and Ajan tokens can never hold it — [`extensions.ops.get`](/reference/routes/extensions.ops.get) reports `missing_secret:` until the owner (or a `secrets:write` developer) enters the value. ## Lifecycle - Minted by the owner ([`tokens.mint`](/reference/routes/tokens.mint), or the Ajanlar ve geliştiriciler admin page); the `mzk_` plaintext is returned **exactly once** and never audited. - Default expiry **90 days** (`tokenDefaultExpiryDays`). - Per-token throttle, default 120/min → HTTP 429 with `Retry-After`. - `token.revoke` kills it immediately and withdraws the token's open proposal. - [`tokens.whoami`](/reference/routes/tokens.whoami) (`GET /v1/tokens/me`) tells a credential its store, kind, scopes, expiry and workspace — the first call an agent should make.