Orbital trace export (GET /v1/audit/export)
Orbital's evolve tool builds model-specialization datasets from the
traces split-brain already logs. This endpoint is the read path.
Endpoint
GET /v1/audit/export Authorization: Bearer <token>
Streams matching audit records as newest-first NDJSON (one JSON object per line), capped at 50,000 records per call.
Query params:
| param | meaning |
|---|---|
since |
ISO-8601 lower bound on received_at |
until |
ISO-8601 upper bound (page older by passing the oldest you got) |
backend |
claude / scalarlm |
label |
routing decision or classifier label, e.g. novel |
limit |
max records (clamped to 50,000) |
scope |
mine (default) or all (admin-attested only) |
Scoping (defense in depth)
owner_emailof the authenticating token is a hard boundary — a token can only ever read its own owner's records.X-Orbital-User-Id(stamped by Orbital's in-pod proxy, which holds the shared token; a pod can't forge it) sub-scopes to a single Orbital user. This is what isolates Orbital users even though all Orbital pods share one token.scope=alllifts the per-user sub-scope (returns the wholeowner_email) and is honored only withX-Orbital-Admin: 1, an attestation only Orbital's trusted proxy / control plane can set.
A direct (non-Orbital) caller has no X-Orbital-* headers, so they get
their entire owner_email — correct, since the token owns it.
Identity capture
The two ingress endpoints (/v1/chat/completions, /v1/messages) read
X-Orbital-User-Id / X-Orbital-Pod-Id and persist them on the
AuditRecord (orbital_user_id, orbital_pod_id). They default to
None for non-Orbital traffic, so the audit schema is backward
compatible.
See Orbital's docs/arch/orbital-traces.md for the full pod-side flow.