/api/v2/ is the surface external developers are meant to call. Where /api/v1/
exposes the platform’s own resources — leads, widgets, knowledge cards — v2
exposes executions: you ask an agent for something, and you get a run with an
id, a status, a cost and a trace.
/api/v1/ is unchanged and is not deprecated by anything here.
Four products, one contract
Runtime
/responses, /conversations, /agents/{id}/runs. Stateless replies,
durable transcripts, and non-conversational agent runs. All three take the
same options and stream with the same events.Documents
/documents. Upload a file, parse it once, read the parsed representation,
hand out expiring download links.Intelligence
/extractions and /reports. A document plus a JSON Schema becomes
validated fields with evidence; an agent plus a task becomes a report.Operations
/jobs, /logs, /webhooks. Poll long work, read what an execution
actually did, and get told when something finishes./knowledge/ingestions
is the one place a stored document becomes something an agent can retrieve.
One shape, everywhere
Learn these four things once and every endpoint on the surface behaves the same way.
Two conventions that surprise people, stated here so they surprise nobody:
A resource in another workspace and a resource that does not exist answer identically
A resource in another workspace and a resource that does not exist answer identically
Both are 404, byte for byte. There is no 403 that confirms existence,
because a 403 turns id-guessing into an inventory.The one place this reads oddly is
preview: a caller without the
agent:preview scope asking for a draft gets 404, not 403. Confirming that
a draft exists but may not be run is exactly the confirmation the rule
exists to withhold.blocked is not failed
blocked is not failed
A workspace out of credits has not had a model failure — nothing went wrong
upstream, the platform declined to spend.
usage_blocked (402) and
rate_limited (429) both end a run as blocked. Every other error code
ends it as failed.Filing the two together is what makes an error-rate dashboard useless.What the caller does not control
The runtime chooses the model, the provider, the sampling parameters and the prompt. A request that tries to set one of them is a 400 that names the field and says why — not a silently ignored key:stream,
response_format, tool_policy, memory_policy, knowledge_policy,
timeout_ms, preview — and the three policy fields can only ever subtract.
There is no value meaning “retrieve more than this agent is configured for”.
Identity is never in the body. Who you are comes from the credential. The
runtime input refuses about thirty reserved keys —
tenant_id, scopes,
billed_to, principal, and the rest — by name rather than dropping them
quietly, so a caller who believed one of them worked finds out immediately.Why the endpoint reference can be believed
The endpoint reference under Endpoint reference in this tab is not written by hand. It is generated from the running code bymanage.py openapi and gated in CI by
manage.py openapi --check, which regenerates the document in memory and
refuses a build where the checked-in file and the code disagree.
Nothing non-trivial in it is typed by a person:
--check also refuses a document that documents a scope no key could ever be
issued, that describes a route that is not wired, or that leaves a routed scoped
operation undescribed.
What it is honest about not being finished
A generated document is only worth the gaps it admits to. Two are worth knowing before you write a client.Paging is not uniform across the surface
Paging is not uniform across the surface
There are four mechanisms, and each operation documents the one it actually
takes:
/logsreturnsnext./documents,/extractions,/reportsand/knowledge/ingestionsreturnnext_cursorand read it back ascursor./conversations/{id}/messagesreturnsnext_cursor, reads it back asafter, and its cursor is a message id rather than an encoded pair./jobspages byoffsetand returns no cursor at all.
+00:00 decodes to a space in a query string and silently
breaks every second page.The idempotent-replay header is spelled two ways
The idempotent-replay header is spelled two ways
/responses, /conversations and /agents/{id}/runs set
Idempotency-Replayed. /jobs, /extractions, /reports and
/knowledge/ingestions set Idempotent-Replay. POST /documents sets
neither and signals a replay by answering 200 where a create answers
201.Read each operation rather than assuming one name. A client checking for the
wrong header reads every replay as a fresh execution — which for a create is
the one conclusion idempotency exists to prevent.Where to start
1
Get a scoped key
Authentication — and grant the minimum scopes the
caller needs, because that is what decides how bad an exposure is.
2
Make one call
Quickstart — a single response, then the same call
streamed.
3
Read the endpoint you need
The generated reference in this tab has a request playground for every one
of the 52 operations.

