# API keys & budgets

API keys are org-scoped credentials for programmatic access. Manage them in [Dashboard → Keys](https://ozma.app/dashboard/keys), REST, CLI, or MCP `set_budget`.

## Create keys

```bash
npx @ozma_app/cli keys create --name "Production agent" --json
npx @ozma_app/cli keys create --name "Capped agent" --budget 5000 --json
```

Plaintext is shown **once**. Store securely.

## Spend caps

Caps live on each key and are enforced **synchronously** on the gateway before upstream calls.

| Field | CLI flag | Meaning |
|-------|----------|---------|
| `budget_cents` | `--budget` | Lifetime spend ceiling |
| `daily_cap_cents` | `--daily-cap` | Max spend per UTC calendar day |
| `per_call_max_cents` | `--per-call-max` | Reject calls priced above this |
| `approval_mode` | `--approval-mode` | **Not enforced** today — stored for forward compatibility only |

Null cap = unlimited for that dimension.

```bash
npx @ozma_app/cli budget set --budget 10000 --daily-cap 500 --per-call-max 50
npx @ozma_app/cli keys patch key_123 --budget 2000 --daily-cap 200
```

**Use `--budget`, `--daily-cap`, `--per-call-max`** — not legacy `--budget-cents` style flags on the budget subcommand.

## Gateway error codes

| Code | When |
|------|------|
| `insufficient_budget` | Lifetime budget would be exceeded |
| `daily_cap_exceeded` | Daily cap would be exceeded |
| `per_call_limit_exceeded` | Single call price too high |

All return HTTP **402**. Read `error.code` — do not confuse daily cap with lifetime budget.

Daily counters reset at **UTC midnight** on the gateway SpendCounter Durable Object.

## Scopes

| Key type | Scopes |
|----------|--------|
| Anonymous register | `catalog:read`, `proxy:call`, `keys:write`, `usage:read` |
| Email verified | + `billing:write`, `provider:write` |

Revoke compromised keys immediately: `ozma keys revoke <id>`.

## Usage visibility

```bash
npx @ozma_app/cli usage --from 2026-07-01 --to 2026-07-22 --json
```

## Design principles

- **Per-key isolation** — delegate one key per agent with its own caps.
- **Fail closed** — set caps are hard limits.
- **No bill on upstream failure** — failed calls refund spend reservation.

## Related

- [Authentication](/docs/getting-started/authentication)
- [Spend governance concept](/docs/concepts/spend-governance)
- [Troubleshooting](/docs/guides/troubleshooting)
