Authentication
Every authenticated request sendsAuthorization: Bearer <token>. There are
two kinds of bearer identity, and each endpoint accepts exactly one:
Workspace keys are minted from the dashboard, shown once, and stored hashed.
Session tokens come from
POST /v1/auth/login and are short-lived; refresh
tokens rotate on every use.
Machine keys deliberately cannot mint other keys or manage workspaces —
key management always requires a signed-in human.
Endpoint groups
- SDK & ingestion, what the SDK talks to:
GET /v1/workspace/me(bootstrap),POST /v1/otlp/v1/traces(OTLP/HTTP protobuf ingest, gzip supported),GET /v1/apply/rules(active optimization rules), andGET /v1/apply/tool-result(a stored tool result under an active reuse rule). - Workspaces & keys: create, list, and delete workspaces; mint, list, and revoke the API keys the SDK uses.
- Observability: agents, usage, decisions, stats summaries and timeseries, traces, events, and findings for a workspace.
- Auth & sessions: signup, login, token refresh, and the JWKS used to verify session tokens.
- Health: liveness and readiness probes.
GET /v1/workspaces/{workspace_id}/usage returns the workspace’s plan, its
current-month ingest counters (accepted events plus any spans dropped by the
event quota or the agent cap), the plan’s caps, and a quota_exceeded flag; it
is the dashboard’s usage meter and the explanation for any capped drop (see
Plans & limits).
GET /v1/workspaces/{workspace_id}/decisions lists the workspace’s
optimization rules as they move through their lifecycle (proposed, shadow,
active, or disabled), with what the gate measured about each. It is an audit
trail of rules, not a per-request event stream: the SDK pulls active rules from
GET /v1/apply/rules and applies them locally, so there is no per-call
decision to log.
Conventions
- Tenancy. A workspace is the unit of isolation; agents and events belong
to it. Requests for a workspace you’re not a member of return
404, not403— whether a workspace exists is itself tenant data. - Pagination. Trace and event listings use opaque keyset cursors
(
next_cursor); pass the cursor back to fetch the next page. Cursors pin the original time window, so pages stay consistent while new data arrives. - Ingestion is forgiving. A span that fails to decode or persist is counted
in
rejected_spanswhile the rest of the batch is accepted; retries are idempotent — redelivered spans never duplicate. - Timestamps are timezone-aware ISO 8601.
The endpoint pages in this section are generated from the backend’s OpenAPI
specification (
api-reference/openapi.json). Refresh it with
scripts/sync-openapi.sh — see the repo README.