Skip to main content
Every OpenType route follows the same small set of rules for URLs, bodies, identifiers, time and money. Read this page once before you write a client, and come back to it when a value looks unfamiliar. Each rule below is enforced by the server, not just recommended.

Base URL and versioning

Every customer route lives under /v1, for example POST /v1/runs and GET /v1/usage. Three routes need no credential: GET /healthz, GET /readyz and GET /openapi.json, which serves the OpenAPI 3.1 document the server itself emits. Every other customer route under /v1 takes Authorization: Bearer <credential>; see Authentication.

Requests

  • JSON in, JSON out. Send request bodies as JSON with Content-Type: application/json. Field names are snake_case.
  • Unknown fields are refused. Every request body rejects fields it does not define, so a typo fails loudly instead of being ignored. On POST /v1/runs this is 400 invalid_body with the message the request body is not valid: the body does not match the schema. On other routes the refusal is a plain-text 422 (see Errors).
  • Unknown query parameters are refused. GET /v1/runs accepts only limit and offset; the usage routes accept only their documented parameters.
  • Body caps. POST /v1/runs and POST /v1/router/select accept up to 4 MiB (4,194,304 bytes) and answer 413 body_too_large above it. Every other route accepts up to 1 MiB and answers a plain-text 413.
  • One header for idempotency. POST /v1/runs requires an Idempotency-Key header of 1 to 255 printable ASCII bytes. No other route reads it. See Idempotency.

Identifiers

Every id is an opaque string with a type prefix. Store ids as strings and compare them exactly; do not parse the part after the prefix. The two run id spellings name the same run. Both are accepted wherever a run id is expected, so you can take a run_id from the ledger and pass it to GET /v1/runs/{run_id}, or the other way round. input_digest and output_digest on a run are 64-character lowercase hex SHA-256 digests.

Timestamps and dates

  • Every timestamp is a string in exactly YYYY-MM-DDTHH:MM:SSZ form: UTC, second precision, a literal Z. For example 2026-09-24T10:12:03Z.
  • Timestamp fields end in _at: created_at, last_used_at, revoked_at, start_at, end_at.
  • Daily rows use a date, YYYY-MM-DD, for example "date": "2026-09-24".
When you send a timestamp, send the same form. The usage routes refuse anything else, including fractional seconds and offsets such as +00:00, with 400 invalid_parameter.

Time windows

GET /v1/usage, GET /v1/usage/ledger and GET /v1/usage/daily take an optional window. Because windows are half-open, consecutive windows never double-count. September 2026 is start_at=2026-09-01T00:00:00Z&end_at=2026-10-01T00:00:00Z.

Money

Every amount is an integer in micro-USD. Amount fields end in _micros. balance_micros and the amount_micros of a billing transaction are signed: a usage row is negative, a purchase is positive. Every other amount is zero or positive. Integers avoid floating-point rounding; divide by 1,000,000 only when you display a dollar value.

Optional fields

Absent values are represented in two ways, depending on the route family:
  • Run responses omit them. A run that produced no output has no output_digest key at all, and a verdict run has no decision key.
  • Keys, usage and billing responses send null. A key that was never used has "last_used_at": null; a quota with no period limit has "period_spend_limit_micros": null.
Write clients that accept both a missing key and a null value.

Pagination

Lists are newest first. See Pagination.

CORS

The API answers browser preflights for the allowed origins configured on the service. When CORS applies: Keep API keys out of browser code. A key in a web page is readable by anyone who loads it; call the API from your server instead. See API key security.

Example: a request that uses every convention

This call reads usage for a half-open window, sends its own request id, and gets integer micro-USD amounts back.

What goes wrong

  • Request ids - trace one request across your logs and ours.
  • Limits - every numeric bound in one table.
  • Errors - the error envelope and what each status means.
  • Pagination - walk run lists and the usage ledger.