REST API Reference
Most integrations should use MCP — it's the supported, higher-level surface, and its tools carry their own schemas. This page is for when you want to script the console's own HTTP API directly: dashboards, provisioning automation, a custom UI.
MCP is the contract; this is the console's own API
The /api/* routes back the web console and evolve with it. MCP tools are
the stable, documented integration surface. Prefer MCP unless you
specifically need something it doesn't expose.
Auth
Every /api/* route (except the public ones below) needs an identity:
- Cookie — a signed session from console login, for browser clients.
- Bearer key —
Authorization: Bearer <key>, for machine clients. A key is device-bound: it authenticates as its owner but is scoped to its one device. Per-key rate limits apply — see Rate limits.
Public, no auth: GET /health, GET /metrics, GET /api/auth/methods, the
OAuth start/callback pair, and POST /api/auth/internal-access/exchange (invitation code; a bare username in dev mode only).
Errors are JSON with a stable error code — route on the code, not the prose:
| Status | error |
Meaning |
|---|---|---|
| 400 | (varies) | Malformed input. |
| 401 | login_required |
No/!valid identity. |
| 402 | out_of_credits |
The account can't fund the action. |
| 404 | not_found |
Missing — or present but not yours (see Security). |
| 429 | rate_limited |
Per-key bucket is dry. |
Auth & account
| Method | Path | Purpose |
|---|---|---|
| GET | /api/auth/methods |
Which login methods are live (dev password / OAuth providers). |
| GET/POST | /api/auth/oauth/{method_id}/start · /callback |
OAuth handshake for one method. |
| POST | /api/auth/internal-access/exchange |
The passwordless door: {credential, purpose} → a signed cookie (web) or a bridge device token (bridge). An invitation code anywhere; a bare username in dev mode only. |
| POST | /api/auth/logout |
Clear the session cookie. |
| GET | /api/auth/whoami |
The current identity. |
| POST | /api/auth/cli/start |
Begin the device-login flow for a command-line client. |
| GET | /api/account |
Account summary. |
| GET | /api/usage · /api/me/metrics |
Usage / metrics for the signed-in account. |
Devices
| Method | Path | Purpose |
|---|---|---|
| GET | /me/devices |
The caller's bound devices (alias-first). |
| PATCH | /me/devices/{device_id} |
Rename — alias only; binding and URLs are unaffected. |
| POST | /api/devices/provision |
Register a device (what flashing calls under the hood). |
| GET | /api/devices/{device_id} |
One device's record. |
| GET | /api/devices/{device_id}/status |
Live status: online, Bluetooth, call state, link RTT/age. |
| GET | /api/devices/{device_id}/metrics · /metrics/range |
Device telemetry, point or windowed. |
| GET | /api/devices/{device_id}/bt-events |
Recent Bluetooth link events. |
| PUT | /api/devices/{device_id}/assistant |
Set the device's standing assistant. |
| GET | /api/devices/{device_id}/credits |
Per-device spend. |
| GET | /api/client_queue?device_id=… |
Live bridge/connection stats for a device. |
| GET | /api/bridge/ws-endpoint |
The WebSocket endpoint a bridge should dial. |
Calls
| Method | Path | Purpose |
|---|---|---|
| GET | /api/calls/history |
Recent calls (the History list). |
| GET | /api/calls/{call_id} |
One call's record. |
| GET | /api/calls/{call_id}/result |
Outcome, summary, transcript, extracted fields. |
| GET | /api/calls/{call_id}/metrics |
Per-call metrics blob. |
| GET | /api/calls/{call_id}/replay |
Replay data — transcript synced to the recording. |
| GET | /api/events |
The live event stream behind the console's monitor. |
Placing and steering calls goes through MCP (place_call, steer_call,
answer_call, …) or the console UI — those are not plain REST endpoints.
Assistants & providers
| Method | Path | Purpose |
|---|---|---|
| GET/POST | /api/assistants |
List / create. |
| GET/PUT | /api/assistants/{id} |
Read / partial edit (edits are versioned). |
| POST | /api/assistants/{id}/duplicate · /reset |
Copy / revert to template. |
| GET | /api/assistants/{id}/versions · /versions/{v} · POST /versions/{v}/restore |
Version history and restore. |
| POST | /api/assistants/assist · /validate · /{id}/ai-check |
Authoring aids: draft, validate, AI review. |
| POST | /api/assistants/{id}/test-call · /trial-device |
Fire a test call / attach a browser trial device. |
| GET | /api/assistants/{id}/stats |
Per-assistant call stats. |
| GET | /api/protocols · /protocols/{protocol} |
Provider roster; one protocol's model/voice lists. |
| POST | /api/protocols/{protocol}/voice-preview |
Sample a voice. |
| GET/POST | /api/me/providers |
List / add your own vendor credentials. |
| GET/PUT/DELETE | /api/me/providers/{id} |
Manage one. |
| POST | /api/me/providers/{id}/validate |
Check a credential works. |
Credits & keys
| Method | Path | Purpose |
|---|---|---|
| GET | /api/credits |
Balance and ledger. |
| POST | /api/credits/topup |
Add credit. |
| GET | /api/keys |
Your API keys (never the secrets). |
| POST | /api/keys |
Mint a device-bound key {device_id, name, rate_per_min?} — the secret is returned once. |
| DELETE | /api/keys/{key_id} |
Revoke a key, effective immediately. |
Rate limits
Machine (Bearer-key) requests are rate-limited per key. Set a key's ceiling
with rate_per_min when you mint it via POST /api/keys; omit it for no limit.
The bucket holds a full minute's burst and refills at rate_per_min / 60 tokens
per second, so a dry bucket returns 429 rate_limited — a code an AI client
can back off on rather than a wall.
Two things that look like rate limits but aren't:
402 out_of_credits— the account can't fund the call. Backing off won't help; it needs credit.- Unauthenticated / invalid-bearer requests are throttled per source IP as well, to blunt key-guessing. That's a defensive limit on bad credentials, not on yours.