Skip to main content
The HTTP API is the operator surface of a running server. Every route lives under /api/*, takes and returns JSON, and authenticates with an API key. The per-endpoint pages in this section render directly from the server’s OpenAPI 3.1 specification, so they never drift from the code.

Base URL

The API is served by the running server, alongside the MCP endpoint and the Studio. Prefix every path with the server’s address:
A local server started with tai serve answers at http://127.0.0.1:8000/api.

Authentication

Every request carries an API key in the x-api-key header. Mint and manage keys with tai keys or the /api/auth/api-keys routes.
A missing or invalid key returns 401 with the error envelope below.
A key’s access-control condition scopes what it may call. See access control for the policy model.

Response envelope

Successful responses wrap their payload in a data field:
Errors return an error field carrying a human-readable message:
The two envelopes never mix — a response carries data or error, never both.

Expression fields

Some string properties in the schema hold a jq expression rather than an ordinary value. Those properties declare themselves: each carries an x-tai42-expression vendor annotation, so a client recognizes the field as an expression and learns its input and output without guessing from the field name.
language is always present and is jq. The rest describe the expression’s context and are emitted only when the declaring surface supplies them: label is a short name for what . is, blurb says what the input document is, keys glosses the input’s known top-level keys as name/gloss pairs, returns says what the result is consumed as, caveats lists evaluation edge cases, and sample carries a representative input document. The annotation is metadata only. An x--prefixed keyword is ignored by JSON Schema validation, so it can never change which values a schema accepts, and a field without one generates a byte-identical schema to a plain string declaration. A client that does not recognize the annotation, or the language it declares, renders the field as a plain string input.
The Studio SDK’s SchemaForm acts on this annotation directly: an annotated field renders the visual jq editor instead of a text box, with no per-field code.

Error model

The reload-gated 503

When the server applies a configuration reload, routes that mutate state return 503 until the reload completes. The body sets reloading to true and the response carries a Retry-After header with the seconds to wait:
Retry the request after the Retry-After interval. Read-only routes stay available throughout a reload.

Unexpected errors and validation

Every error is JSON with an error field and nothing beyond it that could leak. An unexpected, unhandled server error answers a uniform 500 on every serving path — the body is a fixed envelope carrying a correlation id and no internal detail:
The error_id correlates the response to the server-log line that records the full traceback under the same id; the internal exception text — hosts, file paths, stack frames — never reaches the client. Quote the error_id when reporting a fault. On the generic operation body-validation path (the adapter’s 422) and the connectors mutation doors, a validation failure names which fields failed and how, never what you sent: the body lists each offending field’s path and its error type only, with the rejected input values stripped, so a secret submitted in a rejected field there does not ride back out. This stripping is not universal — some named-entity doors interpolate the raw validation error into their 400 body, and pydantic includes the submitted value in that text, so do not rely on the error response to withhold rejected input everywhere.
Regenerate this reference from the running code with tai openapi --out openapi.json — the same offline emitter the docs pipeline runs.