Skip to content

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 keyAuthorization: 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.