Skip to content
Reference

Otium Public API

v0.1.0

The public submit surface. Point an OpenAI-compatible client at our base URL, or call the native job endpoints directly.

Docs

Authentication

Every endpoint except the health probes takes a bearer token: Authorization: Bearer <api-key>. Create a key in the customer portal under Developers. Keys are scoped to one account. Treat them as secrets and rotate them if exposed.

Health

Liveness / readiness probes.

GET /livez No auth

Liveness probe.

Answers only "is this process running". It never consults a dependency, and that is the point: a downed database or payload key store is a readiness condition, not a reason to restart the process. Restarting cannot reach an unreachable vault — it just churns the pod and blocks the rollout that would carry the fix. Unauthenticated.

Responses

StatusMeaning
200The process is running. HealthOK
GET /healthz No auth

Readiness probe.

Reports the observed health of the dependencies that gate every payload path — the database and the payload encryption key store — so a load balancer can route around a degraded instance. Use /livez for liveness. Unauthenticated.

Responses

StatusMeaning
200Healthy. HealthOK
503A gating dependency (database or key store) is unavailable; this instance is degraded. HealthDegraded

Jobs

Otium-native job submission and lookup.

POST /v1/jobs

Submit a job.

Validates, persists, and acknowledges a single inference job, then returns immediately — scheduling and execution happen asynchronously. **Idempotency.** Send the `Idempotency-Key` header (or the body's `idempotency_key`, the same key; sending both with different values is a `400`) to make resubmission safe. With the header, a repeat of the same request returns the original job with the original status and `Idempotent-Replayed: true`, showing the job as it is now; the same key with a different request is a `422`. With only the body field, a repeat returns the existing job with `200`.

Parameters

ParameterIn · typeDescription
Idempotency-Key header · stringMakes a retried create safe. Up to 255 printable ASCII characters (a UUID is ideal), unique per request you mean to make; keys are per account and remembered for 24 hours. A repeat of the same request (same endpoint and byte-identical body) within that window returns the original response with `Idempotent-Replayed: true` and creates nothing. The same key with a different request is a `422`; while the first request is still running it is a `409` with `Retry-After`. A request that failed (any non-2xx) is not remembered, so retrying it with the same key runs it again.

Request body SubmitJobRequest

FieldTypeDescription
model (required)stringWhat to run. An intent alias (e.g. `otium-medium`) or an exact catalog model id. Required. An alias is resolved to a concrete model server-side; an unresolvable value is rejected with 400.
otium OtiumIntentOptional intent extension — declare an outcome (task, quality floor, family) rather than only a model. OpenAI-compatible (stock clients ignore it).
tier TierSLA tier. Omit to default to `remnant`.
rushprioritystandardremnant
payload stringSmall inline request body (PoC). Production payloads live in object storage.
idempotency_key stringPer-tenant key making resubmission safe. A repeat returns the original job.
max_attempts integerMax execution attempts before dead-lettering. Non-positive values default to 3.
Default: 3
boundary BoundaryLocks the job to a residency boundary. Empty means unconstrained.
afapaccaeueu-demenasaukus
sensitivity SensitivityData-sensitivity class. Empty defaults to `internal` (trusted-only).
confidentialinternalpublic
max_tokens integerOutput-token ceiling. Bounds the up-front cost estimate the prepaid gate reserves; 0 uses a default ceiling. A chat-completion body that sets neither max_tokens nor max_completion_tokens is capped at 8192 output tokens when it runs.

Responses

StatusMeaning
200Idempotent replay — the existing job for this idempotency key. Job
201Job created. Job
400Invalid request (bad JSON, missing model, unknown tier or boundary, a malformed Idempotency-Key). NativeError
409An earlier request with this `Idempotency-Key` is still running; retry after `Retry-After`.
422This `Idempotency-Key` was already used with a different request (another body or endpoint). Use a new key for a new request.
429Per-client-IP submit rate limit exceeded.
503Database, payload key store, or catalog briefly unavailable; retry after `Retry-After`. NativeError
GET /v1/jobs/{id}

Get a job.

Returns a job by id. A tenant may only read its own jobs.

Parameters

ParameterIn · typeDescription
id (required)path · string (uuid)Job id.

Responses

StatusMeaning
200The job. Job
404Not found, or owned by another tenant. NativeError

Files

OpenAI-compatible Files API (batch input upload, output download).

GET /v1/files

List files.

Parameters

ParameterIn · typeDescription
purpose query · stringFilter by purpose. Omit for all of the tenant's files.

Responses

StatusMeaning
200A single page of files (OpenAI list envelope). FileList
POST /v1/files

Upload a batch input file.

Uploads a JSONL batch input file (`purpose=batch`). Each line is a `BatchRequestInput`. OpenAI-compatible. Uploads above the server limit are rejected with `413`.

Request body

Responses

StatusMeaning
200Uploaded file metadata. FileObject
400Unsupported purpose or missing file field. OpenAIError
413File exceeds the maximum upload size. OpenAIError
GET /v1/files/{id}

Get file metadata.

Parameters

ParameterIn · typeDescription
id (required)path · stringFile id (e.g. `file-<uuid>`).

Responses

StatusMeaning
200File metadata. FileObject
404No such file (or owned by another tenant). OpenAIError
DELETE /v1/files/{id}

Delete a file.

Parameters

ParameterIn · typeDescription
id (required)path · stringFile id (e.g. `file-<uuid>`).

Responses

StatusMeaning
200Deletion acknowledgement. FileDeleted
404No such file (or owned by another tenant). OpenAIError
GET /v1/files/{id}/content

Download file content.

Streams the raw JSONL content of a file.

Parameters

ParameterIn · typeDescription
id (required)path · stringFile id (e.g. `file-<uuid>`).

Responses

StatusMeaning
200Raw JSONL content.
404No such file (or owned by another tenant). OpenAIError
POST /v1/uploads

Start a multi-part upload of a large batch input file.

OpenAI's Uploads API, for a file too large for one `POST /v1/files` request (a request through the edge is capped at 100 MB). Create the upload with the file's exact size, add its bytes in parts of at most 64 MiB each (in any order, retrying a failed part alone), then complete it with the part ids in file order. The upload expires an hour after it is created; an expired or cancelled upload's parts are deleted. A whole upload may declare at most 8 GiB. A gzipped JSONL is accepted here as on `/v1/files`: it is recognized by its content.

Request body

FieldTypeDescription
filename string
purpose (required)string
batch
bytes (required)integer (int64)The file's exact size; complete checks the parts add up to it.
mime_type string

Responses

StatusMeaning
200The new upload, pending. Upload
400Unsupported purpose, or a size that is zero or above the limit. OpenAIError
POST /v1/uploads/{id}/parts

Add a part to an upload.

Adds up to 64 MiB of the file. Parts may arrive in any order and in parallel; their order in the file is the order `complete` lists them in.

Parameters

ParameterIn · typeDescription
id (required)path · stringUpload id (`upload_…`).

Request body

Responses

StatusMeaning
200The part. UploadPart
400Missing `data` field, or the upload is completed, cancelled or expired. OpenAIError
404No such upload (or owned by another tenant). OpenAIError
413The part is larger than 64 MiB. OpenAIError
POST /v1/uploads/{id}/complete

Complete an upload into a batch input file.

Joins the listed parts, in the order listed, into a file usable as a batch's `input_file_id`. The parts must belong to this upload, appear once each and add up to the size the upload was created with. Completing an upload that already completed returns it again, with the same file. `md5` is accepted and not checked.

Parameters

ParameterIn · typeDescription
id (required)path · stringUpload id (`upload_…`).

Request body

FieldTypeDescription
part_ids (required)array of string
md5 string

Responses

StatusMeaning
200The completed upload, carrying its file. Upload
400An unknown, foreign or repeated part, parts that do not add up to the declared size, or an upload that is cancelled or expired. OpenAIError
404No such upload (or owned by another tenant). OpenAIError
POST /v1/uploads/{id}/cancel

Cancel an upload.

Cancels a pending upload; its parts are deleted shortly after.

Parameters

ParameterIn · typeDescription
id (required)path · stringUpload id (`upload_…`).

Responses

StatusMeaning
200The cancelled upload. Upload
400The upload is already completed or cancelled. OpenAIError
404No such upload (or owned by another tenant). OpenAIError

Batches

OpenAI-compatible Batch API.

POST /v1/chat/completions

Not served (Otium is batch-only).

Otium has no synchronous chat endpoint: it runs work that can wait, on a deadline. This route exists only to say so with an OpenAI-shaped `404` carrying `code: batch_only`, so a gateway or SDK that tries its default path shows the caller a reason instead of a bare "not found". Send the same requests as a batch: upload a JSONL file to `/v1/files`, then create the batch at `/v1/batches`.

Responses

StatusMeaning
404Always. The message names the batch endpoints to use instead. OpenAIError
GET /v1/batches

List batches.

Parameters

ParameterIn · typeDescription
limit query · integerMax batches to return. Defaults to the server's page size.
after query · stringThe `last_id` of the previous page; the page starts with the batch after it. Page until `has_more` is `false`, as the OpenAI SDK does.

Responses

StatusMeaning
200One page of batches, newest first (OpenAI list envelope). BatchList
POST /v1/batches

Create a batch.

Creates a batch over a previously uploaded input file. OpenAI-compatible. **Completion window → SLA tier.** `completion_window` accepts OpenAI's `24h` (and empty, treated as `24h`), the shorthands `1h` / `6h` / `7d` / `168h`, and Otium's own tier names as an extension — the flexible-deadline knob. **Data residency.** Set `metadata.boundary` (e.g. `us`, `eu`) to lock every job in the batch to a residency boundary. **Upgrades.** By default a job may run on a warm, larger model at its own product's price. Set `metadata.allow_upgrade` to `"false"` to keep this batch on the models it names, or `"true"` to allow it on an account that has upgrades switched off. **Idempotency.** Send an `Idempotency-Key` header and a repeat of the same request returns the original batch object byte for byte, with `Idempotent-Replayed: true`, instead of creating a second batch over the same file.

Parameters

ParameterIn · typeDescription
Idempotency-Key header · stringMakes a retried create safe. Up to 255 printable ASCII characters (a UUID is ideal), unique per request you mean to make; keys are per account and remembered for 24 hours. A repeat of the same request (same endpoint and byte-identical body) within that window returns the original response with `Idempotent-Replayed: true` and creates nothing. The same key with a different request is a `422`; while the first request is still running it is a `409` with `Retry-After`. A request that failed (any non-2xx) is not remembered, so retrying it with the same key runs it again.

Request body CreateBatchRequest

FieldTypeDescription
input_file_id (required)stringId of an uploaded file with purpose `batch`, owned by the caller.
endpoint stringThe only endpoint supported today.
/v1/chat/completions
Default: /v1/chat/completions
completion_window stringOpenAI `24h` (default), the shorthands `1h` / `6h` / `7d` / `168h`, or an Otium tier name (`rush`, `priority`, `standard`, `remnant`).
Default: 24h
metadata map of stringUp to 16 string key/value pairs. The reserved key `boundary` locks every job in the batch to a residency boundary. A key a gateway adds on its caller's behalf (`otari_user_id`) does not count against the 16.

Responses

StatusMeaning
200The created batch (status `validating`). Batch
400Invalid request (bad JSON, missing input_file_id, unsupported endpoint/window, too much metadata, invalid boundary or allow_upgrade). OpenAIError
404input_file_id does not exist or is not owned by the caller. OpenAIError
409An earlier request with this `Idempotency-Key` is still running; retry after `Retry-After`.
422This `Idempotency-Key` was already used with a different request (another body or endpoint). Use a new key for a new request.
503Database briefly unavailable; retry after `Retry-After`. OpenAIError
GET /v1/batches/{id}

Get a batch.

The OpenAI batch, plus `waiting` while it is `in_progress`: its requests that have not started, by model, and why. `request_counts` moves only as requests finish, so `waiting` is what tells work that is held from work that is stuck. A request is `held` while the provisioner gathers enough work to share a GPU's boot or waits for a cheaper price (never past `latest_start`), `starting` while capacity is being started (a cold start takes 15-30 minutes, longer when a cloud has no capacity), `queued` behind a serving worker, or `billing_hold` on the account's funds or monthly spend cap. OpenAI clients ignore the field.

Parameters

ParameterIn · typeDescription
id (required)path · stringBatch id (e.g. `batch_<uuid>`).

Responses

StatusMeaning
200The batch.
404No such batch (or owned by another tenant). OpenAIError
POST /v1/batches/{id}/cancel

Cancel a batch.

Requests cancellation: the batch moves to `cancelling`, the processor stops outstanding jobs and finalizes what completed. Idempotent while already `cancelling`. Cancelling a terminal batch is a `409`.

Parameters

ParameterIn · typeDescription
id (required)path · stringBatch id (e.g. `batch_<uuid>`).

Responses

StatusMeaning
200The batch, now `cancelling` (or unchanged if already cancelling). Batch
404No such batch (or owned by another tenant). OpenAIError
409The batch is in a terminal status and cannot be cancelled. OpenAIError

Models

OpenAI-compatible model listing.

GET /v1/models

List the models you can submit to.

The offered products plus the previews granted to your account (`preview: true`), OpenAI-compatible (`client.models.list()` works unchanged). Each `id` is what a request's `model` field names. `context_window` is the most tokens, prompt plus completion, one request may use; it is omitted when one number would not be true (a product that runs several models). Sorted by `id`; an empty catalog is `data: []`.

Responses

StatusMeaning
200The models. ModelList

Workflows

Workflow graphs — publish, validate, unit-test, and read compiled plans.

GET /v1/workflows

List workflows.

Your workflows, one entry per name, with the latest version and how many versions exist.

Responses

StatusMeaning
200The workflows. WorkflowList
401No credential, or one that is invalid, expired or revoked. NativeError
503Workflows are not available on this deployment. NativeError
POST /v1/workflows

Publish a workflow version.

Validates, compiles and stores a workflow document as a new version of the workflow it names. Send the YAML as the raw body (`curl --data-binary @workflow.yaml`), or as JSON `{"document": "<yaml>"}` with `Content-Type: application/json`. Up to 1 MiB. **Idempotent.** Publishing a document identical to an existing version creates nothing: it returns that version with `200` and `created: false`, so publishing on every merge is safe. A new version is `201` with `created: true`. A document that does not compile is `422` with every finding in `diagnostics`. So is one whose `tools.endpoint` names a tool endpoint you have not registered.

Request body WorkflowDocumentEnvelope

FieldTypeDescription
document (required)stringThe workflow document, as YAML text.

Responses

StatusMeaning
200Replay. The document matches an existing version, which is returned. WorkflowCompileResult
201A new version was created. WorkflowCompileResult
401No credential, or one that is invalid, expired or revoked. NativeError
413The document is over 1 MiB. NativeError
422The document was rejected. `diagnostics` lists every finding. WorkflowCompileResult
503Workflows are not available on this deployment. NativeError
POST /v1/workflows/validate

Validate a workflow document without publishing it.

Compiles a document and returns the findings, and, when it compiles, its summary (critical path, durations, estimated cost) and a Mermaid diagram. Writes nothing. The body is the same as for publishing. Validation always answers `200`; read `ok` and `diagnostics` for the verdict.

Parameters

ParameterIn · typeDescription
plan query · boolean`true` includes the compiled plan in the result.

Request body WorkflowDocumentEnvelope

FieldTypeDescription
document (required)stringThe workflow document, as YAML text.

Responses

StatusMeaning
200The compile result. `created` and `version` are never set here. WorkflowCompileResult
401No credential, or one that is invalid, expired or revoked. NativeError
413The document is over 1 MiB. NativeError
POST /v1/workflows/test

Run a workflow's unit tests.

Runs a test suite (the contents of a `*.test.yaml` file) against a workflow document, with each case's node outputs supplied by the suite instead of a model. Writes nothing and runs no inference. The same runner as `otiumctl workflow test`. A suite that runs is `200` whether or not its cases pass; the report says which. A document that does not compile, a suite that does not parse or is invalid, or a suite that does not finish within 15 seconds is `422`.

Request body WorkflowTestRequest

FieldTypeDescription
document (required)stringThe workflow document under test, as YAML text. Up to 1 MiB.
tests (required)stringThe test suite (a `*.test.yaml` file's contents), as YAML or JSON. Up to 1 MiB.
run stringRun only the cases whose name contains this.

Responses

StatusMeaning
200The suite ran. WorkflowTestReport
400The body is not JSON with a non-empty `document` and `tests`. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
413The request is too large. NativeError
422The document or the suite was rejected, or the suite timed out. NativeError
GET /v1/workflows/{name}

List a workflow's versions.

Parameters

ParameterIn · typeDescription
name (required)path · stringThe workflow's name, as its document declares it.

Responses

StatusMeaning
200Every version of the workflow. WorkflowVersionList
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflows are not available on this deployment. NativeError
GET /v1/workflows/{name}/{version}

Get a workflow version and its document.

Parameters

ParameterIn · typeDescription
name (required)path · stringThe workflow's name, as its document declares it.
version (required)path · stringA version number (1 or more), or `latest` for the newest published version. Anything else is `400`.

Responses

StatusMeaning
200The version, with its document. WorkflowDetail
400The version is not a positive number or `latest`. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflows are not available on this deployment. NativeError
DELETE /v1/workflows/{name}/{version}

Deprecate a workflow version.

Stops new runs from using the version. Nothing is deleted: existing runs reference it, and it stays readable. A purged version cannot be changed (`409`).

Parameters

ParameterIn · typeDescription
name (required)path · stringThe workflow's name, as its document declares it.
version (required)path · stringA version number (1 or more), or `latest` for the newest published version. Anything else is `400`.

Responses

StatusMeaning
200The version, now deprecated. WorkflowVersion
400The version is not a positive number or `latest`. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409The version was purged and cannot be changed. NativeError
503Workflows are not available on this deployment. NativeError
GET /v1/workflows/{name}/{version}/plan

Get a workflow version's compiled plan.

The plan the scheduler runs from: topological order, critical path, edges, barriers, affinity and cache groups, and per-node estimates. `mermaid` and `summary` come from the document, so a purged version returns its plan without them.

Parameters

ParameterIn · typeDescription
name (required)path · stringThe workflow's name, as its document declares it.
version (required)path · stringA version number (1 or more), or `latest` for the newest published version. Anything else is `400`.
planner query · integerA specific planner version's plan. Omitted, the newest plan for the version.

Responses

StatusMeaning
200The plan. WorkflowPlan
400The version is not a positive number or `latest`. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflows are not available on this deployment. NativeError

Assets

Versioned asset bundles a workflow's prompts read.

GET /v1/assets

List asset bundles.

Your asset bundles: the versioned reference data a workflow's prompts render from. One entry per bundle, with its latest version.

Responses

StatusMeaning
200The bundles. AssetBundleList
401No credential, or one that is invalid, expired or revoked. NativeError
503Asset bundles are not available on this deployment. NativeError
POST /v1/assets

Publish an asset bundle version.

Publishes a new version of a bundle. Each entry in `assets` is either a string (one value shared by every run) or an object of key to string (one value per key). Publishing content identical to the bundle's latest version creates nothing: it returns that version with `200` and `created: false`, so a CI job can republish on every run. A new version is `201`. A bundle is at most 8 MiB.

Request body AssetPublishRequest

FieldTypeDescription
bundle (required)stringThe bundle to publish a version of. Created on first publish.
comment stringA note kept with the version.
assets (required)objectAsset name to value: a string for one value shared by every run, or an object of key to string for one value per key.

Responses

StatusMeaning
200Identical to the latest version. Nothing was created. AssetPublishResult
201A new version was published. AssetPublishResult
400The body or a bundle name, asset or size is invalid. The message says which. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
413The body is over 16 MiB. NativeError
503Asset bundles are not available on this deployment. NativeError
GET /v1/assets/{bundle}

List a bundle's versions.

Every version of one bundle, newest first. Metadata only, never content.

Parameters

ParameterIn · typeDescription
bundle (required)path · stringBundle name.

Responses

StatusMeaning
200The versions. AssetVersionList
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Asset bundles are not available on this deployment. NativeError
GET /v1/assets/{bundle}/{version}

Get a bundle version with its content.

One version's metadata and its assets. A purged version has no assets.

Parameters

ParameterIn · typeDescription
bundle (required)path · stringBundle name.
version (required)path · integerVersion number.

Responses

StatusMeaning
200The version and its content. AssetDetail
400The version is not a positive integer. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Asset bundles are not available on this deployment. NativeError
DELETE /v1/assets/{bundle}/{version}

Deprecate a bundle version.

Stops new runs from pinning this version. Runs that already pinned it keep it. Its content stays; to destroy the content, purge it.

Parameters

ParameterIn · typeDescription
bundle (required)path · stringBundle name.
version (required)path · integerVersion number.

Responses

StatusMeaning
200The version, now deprecated. AssetVersion
400The version is not a positive integer. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409The version cannot change from its current state. NativeError
503Asset bundles are not available on this deployment. NativeError
POST /v1/assets/{bundle}/{version}/purge

Purge a bundle version's content.

Destroys the version's content and keeps its record, so runs that used it still say which version they rendered from. Refused with `409` while a live run pins the version: wait for it to finish.

Parameters

ParameterIn · typeDescription
bundle (required)path · stringBundle name.
version (required)path · integerVersion number.

Responses

StatusMeaning
200The version, now purged. AssetVersion
400The version is not a positive integer. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409A live run pins this version, or it cannot change from its current state. NativeError
503Asset bundles are not available on this deployment. NativeError

Runs

Workflow execution — run sets, runs, their nodes and attempts.

GET /v1/run-sets

List run sets.

Your run sets, oldest first. A batch that names a workflow becomes one run set with one run per input line; a continuation is a run set too (`continues_set_id`). Keyset-paged: pass the previous page's `next_cursor` as `after`.

Parameters

ParameterIn · typeDescription
status query · stringComma-separated `RunStatus` values to include, e.g. `failed,partial`. An unknown value filters nothing rather than failing.
after query · stringThe previous page's `next_cursor`.
limit query · integerPage size. Above 1000 is capped; an unreadable value uses the default.

Responses

StatusMeaning
200A page of run sets. RunSetList
401No credential, or one that is invalid, expired or revoked. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}

Get a run set.

A run set's aggregate state: its status, how many runs finished, a live per-status count, and the queued work being held before it starts (`holds`). **Held is not stuck.** Otium may hold queued work before booting a GPU: to gather enough work to share one boot (`gathering`), or to wait for a cheaper spot price (`price`). The set still reads `running` (the work is accepted and will run) and `holds` names the nodes held, how many runs each, and the latest start, by which capacity is started regardless. **Two clocks.** `execution_budget_seconds` is the SLA bought (it stops while a run waits on you); `expires_at` is the separate wall-clock bound. They are never collapsed into one "time remaining". **Set-scope nodes.** When the workflow has `scope: set` nodes, `set_run` names the run that carries them: `{status: "pending"}` until every item has finished, then its id, status and outcome. The counts are items only; the set is `running` until the set run has finished too.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.

Responses

StatusMeaning
200The run set. RunSet
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}/runs

List a run set's runs.

One run per input item, keyset-paged like the set listing. Items only: the set run (custom_id `$set`), which carries a workflow's set-scope nodes, is not one of them and is never listed here; read it with `GET /v1/run-sets/{id}/set`.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.
status query · stringComma-separated `RunStatus` values to include, e.g. `failed,partial`. An unknown value filters nothing rather than failing.
custom_id query · stringOnly the run for this input line's `custom_id`.
finished_after query · string (date-time)Only runs that finished strictly after this time (RFC 3339): what finished since the last poll. Pass the latest `finished_at` already seen less a minute, and skip run ids already handled; runs finish on several writers, so one can commit a moment after a run that finished later, and the overlap is what keeps it from being missed.
after query · stringThe previous page's `next_cursor`.
limit query · integerPage size. Above 1000 is capped; an unreadable value uses the default.

Responses

StatusMeaning
200A page of runs. RunList
400`finished_after` is not an RFC 3339 time. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}/set

Get a run set's set run.

The run that carries the workflow's set-scope nodes, which run once per submission after every item has finished, exactly as `GET /v1/runs/{id}` returns it. Its `custom_id` is `$set`. While the items are still running the answer is `409` with their counts, so a client can poll this one URL for the result that reads across the whole submission.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.

Responses

StatusMeaning
200The set run. Run
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, owned by another tenant, a workflow with no set-scope nodes, or a set that ended before its items finished. NativeError
409The items are still running; the set run does not exist yet. SetRunPending
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}/output

Download a run set's results.

JSONL, one line per run: the same lines a workflow batch writes to its output file. Any set has one, including a continuation, which an API call created and which therefore has no batch file of its own.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.

Responses

StatusMeaning
200The results.
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
POST /v1/run-sets/{id}/rerun

Rerun a run set from a step.

Starts a new run set over this one's items, against a version of the same workflow, that reruns the steps in `from` and everything downstream of them and reuses this set's recorded output for every other step. Use it to measure a change to one step without buying the steps before it again: only the rerun steps are charged. Every reused step must be identical in both versions, its prompt, product, schemas, validators, condition and inputs included; if one changed, the answer is `409` naming it, so add it to `from`. A recorded skip is reused as made. Items whose content was deleted under the retention policy, or whose reused steps did not finish, are left out and counted in `excluded`. `dry_run: true` creates nothing and answers what the rerun would cover and cost. Like a batch line, a run your balance or spend cap cannot cover is created `hold`. Idempotent: the same source, version and steps return the set the first call created, with `200` and `existing: true`.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.

Request body RerunRequest

FieldTypeDescription
version integerThe workflow version to rerun against. 0 or absent is the latest published.
from (required)array of stringThe steps to rerun. They and every step downstream of them run again.
dry_run booleanCreate nothing; answer what the rerun would cover and cost.

Responses

StatusMeaning
200A dry run, or the rerun an identical earlier call created. RerunResult
201The rerun was created. RerunResult
400The body is not a rerun request. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409Still running, an unknown step or version, or a reused step that differs between the versions. NativeError
POST /v1/run-sets/{id}/continue

Continue a run set.

Starts a new run set that resumes every unfinished run in this one. Nodes that already produced a valid output are carried over (`inherited_nodes`) and are not bought again; only the rest run (`rerunning_nodes`). It is a new purchase with a fresh reservation, admitted like a batch line: a run your balance or monthly spend cap cannot cover is created `hold` (`held_runs`) and starts on its own once it can. Idempotent: a repeat returns the continuation the first call created with `200` and `existing: true`. It is `409` when there is nothing to continue, when the set has not stopped yet, or when its content was deleted under the retention policy.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.

Responses

StatusMeaning
200Replay. The continuation an earlier call created. Continuation
201The continuation was created. Continuation
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409Nothing to continue, still running, or the content was deleted. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}/nodes/{key}/parked

List the runs waiting at an external node.

The runs in a set currently parked at one external node, with each one's rendered input, so you can do the work and resume them in bulk. The cohort is live, not a snapshot: runs arrive at a park at different times, so an empty page now does not mean the cohort is finished, and you resume in waves.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.
key (required)path · stringThe node's key in the workflow document.
after query · stringThe previous page's `next_cursor`.
limit query · integerPage size. Out-of-range values use the default.

Responses

StatusMeaning
200A page of parked runs. ParkedCohort
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/run-sets/{id}/nodes/{key}/output.jsonl

Download one node's results across a set, in OpenAI batch-output format.

One node's results for every run in the set, each line a `BatchRequestOutput`, so code that already reads OpenAI batch output keeps working while you move a pipeline onto a workflow one stage at a time. An unknown node key is `404`, never an empty file.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.
key (required)path · stringThe node's key in the workflow document.

Responses

StatusMeaning
200JSONL, one `BatchRequestOutput` per line.
401No credential, or one that is invalid, expired or revoked. NativeError
404No such set, or the workflow has no node with this key. NativeError
503Workflow runs are not available on this deployment. NativeError
POST /v1/run-sets/{id}/nodes/{key}/resume

Resume parked runs in bulk.

Resumes runs parked at an external node from one JSONL body, a line per run: `{"custom_id": "...", "output": {...}}`. Each output goes through the node's validators. Safe to retry after a timeout: a line naming a run already resumed is a no-op that reports success, so re-sending the whole file is always correct. One bad line fails that line only (see `results`) and never rejects the body. Up to 32 MiB per body and 4 MiB per line.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun set id.
key (required)path · stringThe node's key in the workflow document.

Request body

Responses

StatusMeaning
200A result per line. BulkResumeResult
400The body could not be read as lines (a line over 4 MiB). NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
413The body is over 32 MiB. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/runs/{id}

Get a run.

One input item's run through the graph: each node's status, output, and, while the node waits behind a held cold start, `hold`. **Three durations.** `budget_consumed_seconds` is the SLA clock, which includes the wait for capacity; `parked_seconds` is time spent waiting on you, which the SLA clock does not count; `execution_seconds` is the time workers actually spent on the run, retries included. Compare `execution_seconds` with a plan's p95 execution.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun id.

Responses

StatusMeaning
200The run. Run
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
GET /v1/runs/{id}/nodes/{key}/attempts

List a node's attempts.

Every attempt at one node, oldest first: the model and region that served it, its output (rejected or accepted), the validator verdicts, tokens and cost, and when a worker leased it. Debug a validator here: a rejected output is visible only on its attempt.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun id.
key (required)path · stringThe node's key in the workflow document.

Responses

StatusMeaning
200The node's attempts. NodeAttempts
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
POST /v1/runs/{id}/cancel

Cancel a run.

Stops one run: its unfinished nodes end `failed` with reason `cancelled`, jobs not yet leased are stopped, and the run ends `cancelled`. Cancelling a finished run changes nothing and returns it.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun id.

Responses

StatusMeaning
200The run, after cancelling. Run
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Workflow runs are not available on this deployment. NativeError
POST /v1/runs/{id}/continue

Continue one run.

The single-run form of `POST /v1/run-sets/{id}/continue`, for debugging. Same idempotency and `409` rules.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun id.

Responses

StatusMeaning
200Replay. The continuation an earlier call created. Continuation
201The continuation was created. Continuation
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409Nothing to continue, still running, or the content was deleted. NativeError
503Workflow runs are not available on this deployment. NativeError
POST /v1/runs/{id}/nodes/{key}/resume

Resume one parked run.

Supplies an external node's output for one run. For more than a handful of runs use the set's bulk resume. A rejected output leaves the node parked, so you can send it again.

Parameters

ParameterIn · typeDescription
id (required)path · stringRun id.
key (required)path · stringThe node's key in the workflow document.

Request body ResumeRequest

FieldTypeDescription
output (required)objectThe external node's output, checked by its validators.

Responses

StatusMeaning
200Resumed. ResumeOK
400The body is not `{"output": ...}`. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
409The node is not parked (most often, it was already resumed). NativeError
413The body is over 32 MiB. NativeError
422The node's validators rejected the output. The node stays parked. ResumeRejected
503Workflow runs are not available on this deployment. NativeError

Webhooks

Lifecycle notifications. A notification carries ids and counts, never content.

GET /v1/webhooks

List webhook endpoints.

Your registered endpoints, and the events you can subscribe to. A notification carries ids, counts and a link to an authenticated listing, never a prompt or a result.

Responses

StatusMeaning
200The endpoints and the event vocabulary. WebhookEndpointList
401No credential, or one that is invalid, expired or revoked. NativeError
503Webhooks are not available on this deployment. NativeError
POST /v1/webhooks

Register a webhook endpoint.

Registers an `https` URL to notify. With no `events`, it subscribes to the set-level events only (`run_set.completed`, `run_set.node_parked`); per-run events fire once per item and must be named. At most 10 endpoints per account. The response carries the signing secret. It is shown once and cannot be retrieved again; if you lose it, rotate. Each delivery is signed in the `Otium-Signature` header.

Request body WebhookEndpointRequest

FieldTypeDescription
url stringAn https URL. Required to register.
description string
events array of WebhookEventEvents to subscribe to. Empty or absent on register means the set-level defaults.
enabled boolean

Responses

StatusMeaning
201Registered. The secret is in this response only. WebhookRegistration
400No URL, a URL that is not https or resolves to a private address, an unknown event, or the endpoint limit reached. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
503Webhooks are not available on this deployment. NativeError
GET /v1/webhooks/deliveries

List recent webhook deliveries.

Recent deliveries to all your endpoints, newest first: what was sent, how many tries, and what your endpoint answered. A delivery that used up its retries is kept as `dead`.

Parameters

ParameterIn · typeDescription
limit query · integerHow many deliveries to return. An unreadable value uses the default.

Responses

StatusMeaning
200The deliveries. WebhookDeliveryList
401No credential, or one that is invalid, expired or revoked. NativeError
503Webhooks are not available on this deployment. NativeError
GET /v1/webhooks/{id}

Get a webhook endpoint.

One endpoint, with its last success and failure. Never the secret.

Parameters

ParameterIn · typeDescription
id (required)path · stringWebhook endpoint id.

Responses

StatusMeaning
200The endpoint. WebhookEndpoint
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Webhooks are not available on this deployment. NativeError
PATCH /v1/webhooks/{id}

Update a webhook endpoint.

Changes the URL, description, subscribed events or enabled flag. A field left out is unchanged.

Parameters

ParameterIn · typeDescription
id (required)path · stringWebhook endpoint id.

Request body WebhookEndpointRequest

FieldTypeDescription
url stringAn https URL. Required to register.
description string
events array of WebhookEventEvents to subscribe to. Empty or absent on register means the set-level defaults.
enabled boolean

Responses

StatusMeaning
200The updated endpoint. WebhookEndpoint
400An invalid URL or an unknown event. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Webhooks are not available on this deployment. NativeError
DELETE /v1/webhooks/{id}

Delete a webhook endpoint.

Removes the endpoint and its delivery history.

Parameters

ParameterIn · typeDescription
id (required)path · stringWebhook endpoint id.

Responses

StatusMeaning
200Deleted. WebhookDeleted
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Webhooks are not available on this deployment. NativeError
POST /v1/webhooks/{id}/rotate

Rotate a webhook endpoint's signing secret.

Issues a new signing secret, shown once in this response.

Parameters

ParameterIn · typeDescription
id (required)path · stringWebhook endpoint id.

Responses

StatusMeaning
200The endpoint and its new secret. WebhookRegistration
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Webhooks are not available on this deployment. NativeError
GET /v1/webhooks/{id}/deliveries

List one endpoint's recent deliveries.

As `GET /v1/webhooks/deliveries`, for one endpoint.

Parameters

ParameterIn · typeDescription
id (required)path · stringWebhook endpoint id.
limit query · integerHow many deliveries to return. An unreadable value uses the default.

Responses

StatusMeaning
200The deliveries. WebhookDeliveryList
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Webhooks are not available on this deployment. NativeError

Tools

Endpoints a workflow's tool nodes call, signed by Otium.

GET /v1/tools

List tool endpoints.

Your registered tool endpoints: the URLs a workflow's tool nodes call, named by `tools: { endpoint }` in the workflow document.

Responses

StatusMeaning
200The endpoints. ToolEndpointList
401No credential, or one that is invalid, expired or revoked. NativeError
503Tool endpoints are not available on this deployment. NativeError
POST /v1/tools

Register a tool endpoint.

Registers an `https` URL under a name a workflow can refer to. The name is lowercase letters, digits, `-` or `_`, and cannot change later. At most 20 endpoints per account. The response carries the signing secret Otium signs each call with. It is shown once and cannot be retrieved again; if you lose it, rotate.

Request body ToolEndpointRequest

FieldTypeDescription
name stringLowercase letters, digits, `-` or `_`.
url stringAn https URL.
description stringUp to 200 characters.

Responses

StatusMeaning
201Registered. The secret is in this response only. ToolRegistration
400A missing or invalid name or URL, a description over 200 characters, or the endpoint limit reached. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
409An endpoint with this name already exists. NativeError
503Tool endpoints are not available on this deployment. NativeError
GET /v1/tools/{id}

Get a tool endpoint.

One endpoint. Never the secret.

Parameters

ParameterIn · typeDescription
id (required)path · stringTool endpoint id.

Responses

StatusMeaning
200The endpoint. ToolEndpoint
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Tool endpoints are not available on this deployment. NativeError
PATCH /v1/tools/{id}

Update a tool endpoint.

Changes the URL or description. A field left out is unchanged. The name cannot change, because published workflows refer to it; register a new endpoint instead.

Parameters

ParameterIn · typeDescription
id (required)path · stringTool endpoint id.

Request body ToolEndpointRequest

FieldTypeDescription
name stringLowercase letters, digits, `-` or `_`.
url stringAn https URL.
description stringUp to 200 characters.

Responses

StatusMeaning
200The updated endpoint. ToolEndpoint
400A name was sent, or the URL or description is invalid. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Tool endpoints are not available on this deployment. NativeError
DELETE /v1/tools/{id}

Delete a tool endpoint.

Removes the endpoint.

Parameters

ParameterIn · typeDescription
id (required)path · stringTool endpoint id.

Responses

StatusMeaning
204Deleted.
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Tool endpoints are not available on this deployment. NativeError
POST /v1/tools/{id}/rotate

Rotate a tool endpoint's signing secret.

Issues a new signing secret, shown once in this response. The old one stops working at once.

Parameters

ParameterIn · typeDescription
id (required)path · stringTool endpoint id.

Responses

StatusMeaning
200The endpoint and its new secret. ToolRegistration
401No credential, or one that is invalid, expired or revoked. NativeError
404Not found, or owned by another tenant. NativeError
503Tool endpoints are not available on this deployment. NativeError

Account

The signed-in person's account and API keys. A CLI token only; an API key gets 403.

GET /v1/account

Get the signed-in account.

The account the CLI token belongs to. An API key gets `403`.

Responses

StatusMeaning
200The account. Account
401No credential, or one that is invalid, expired or revoked. NativeError
403An API key on an account route. Use a CLI token (otiumctl auth login). NativeError
GET /v1/api-keys

List API keys.

The account's API keys, newest first, revoked ones included. A key's secret is never returned here; `last_four` identifies it. An API key gets `403`: only a person (a CLI token) manages keys.

Responses

StatusMeaning
200The keys. APIKeyList
401No credential, or one that is invalid, expired or revoked. NativeError
403An API key on an account route. Use a CLI token (otiumctl auth login). NativeError
POST /v1/api-keys

Create an API key.

Mints an API key for programs and CI. The response carries the full `secret` once: it is never stored or shown again, so save it now. An API key gets `403`.

Request body APIKeyCreateRequest

FieldTypeDescription
name (required)string
expires_days integerDays until the key expires. Absent, it expires in 90 days. `0` is an explicit "never expires", which you have to ask for. Existing keys keep the expiry they were made with.
service booleanA key for a system rather than a person. Only an org's owners and admins may create one.

Responses

StatusMeaning
201The key, with its secret. APIKeyCreated
400Missing or over-long `name`, a negative `expires_days`, or an unreadable body. NativeError
401No credential, or one that is invalid, expired or revoked. NativeError
403An API key on an account route. Use a CLI token (otiumctl auth login). NativeError
503API keys are unavailable on this deployment. NativeError
DELETE /v1/api-keys/{id}

Revoke an API key.

Revokes one of the account's keys. Revoking twice is not an error. An API key gets `403`.

Parameters

ParameterIn · typeDescription
id (required)path · stringAPI key id.

Responses

StatusMeaning
200Revoked. APIKeyRevoked
401No credential, or one that is invalid, expired or revoked. NativeError
403An API key on an account route. Use a CLI token (otiumctl auth login). NativeError
404Not found, or owned by another tenant. NativeError
503API keys are unavailable on this deployment. NativeError

CLI sign-in

The OAuth device grant `otiumctl auth login` runs, and token renewal.

POST /v1/auth/device No auth

Start a CLI sign-in.

Starts the OAuth device authorization grant (RFC 8628) that `otiumctl auth login` runs. Show the person `user_code` and `verification_uri`; they approve it in the portal, signed in and re-entering their password (and second factor when MFA is on). Then poll `POST /v1/auth/device/token` every `interval` seconds until `expires_in` runs out. Unauthenticated and rate-limited per client IP.

Request body DeviceStartRequest

FieldTypeDescription
device_name stringShown on the approval page and the Devices list, e.g. `otiumctl on build-01`. Optional.

Responses

StatusMeaning
200The sign-in was started. DeviceStart
400`device_name` is over 100 characters. NativeError
429Rate limit exceeded for this client IP.
503CLI sign-in is unavailable, or the database is down. NativeError
POST /v1/auth/device/token No auth

Poll for a CLI sign-in's token.

Until the person approves the sign-in, this answers `400` with an RFC 8628 error code: `authorization_pending` (keep polling), `slow_down` (poll less often), `access_denied`, `expired_token` (start again) or `invalid_grant` (unknown or already used). Once approved it returns the credentials, exactly once. Unauthenticated and rate-limited per client IP.

Request body DevicePollRequest

FieldTypeDescription
device_code (required)stringFrom `POST /v1/auth/device`.

Responses

StatusMeaning
200Approved. The sign-in's credentials. TokenResponse
400Not approved (yet), or no `device_code` was sent. TokenError
429Rate limit exceeded for this client IP.
503CLI sign-in is unavailable, or the database is down. NativeError
POST /v1/auth/token/refresh No auth

Renew a CLI sign-in.

Exchanges a refresh token for a new access token and a new refresh token (RFC 6749 §6). Each refresh token works once: presenting one that was already used revokes the sign-in. A sign-in ends after 30 days unused or 90 days in all; any failure is `401` `invalid_grant`, and the CLI signs in again. Unauthenticated and rate-limited per client IP.

Request body TokenRefreshRequest

FieldTypeDescription
refresh_token (required)string

Responses

StatusMeaning
200The renewed credentials. TokenResponse
400No `refresh_token` was sent (`invalid_request`). TokenError
401The sign-in has ended (`invalid_grant`). TokenError
429Rate limit exceeded for this client IP.
503CLI sign-in is unavailable, or the database is down. NativeError
DELETE /v1/auth/token

Sign this CLI token out.

Revokes the user token the request authenticated with (`otiumctl auth logout`). Other sign-ins are managed from the portal's Devices page. An API key gets `403`.

Responses

StatusMeaning
200Signed out. TokenRevoked
401No credential, or one that is invalid, expired or revoked. NativeError
403An API key on an account route. Use a CLI token (otiumctl auth login). NativeError

Schemas

The object shapes the endpoints above accept and return.

ModelList

FieldTypeDescription
object (required)string
list
data (required)array of Model

Model

FieldTypeDescription
id (required)stringThe product to name in a request's `model` field.
object (required)string
model
created (required)integerUnix seconds the product was created; 0 when unknown.
owned_by (required)string
context_window integerMost tokens (prompt plus completion) one request may use.
preview booleanA preview granted to your account: usable by you, not offered to everyone. Omitted for an offered model.
warm booleanA worker is serving this model now, so work starts without a cold start (15-30 minutes). A snapshot: idle workers are released within minutes.

Tier

SLA tier — the completion window the caller will wait.

rushprioritystandardremnant

Boundary

Data-residency boundary (never a raw cloud region). Empty means unconstrained. Coarse and fine tags coexist (e.g. a region in `eu` may also be in `eu-de`).

afapaccaeueu-demenasaukus

Sensitivity

Data-sensitivity class. Empty defaults to `internal` (trusted-only). Sets the minimum worker trust tier the job may run on. See docs/trust-tiers.md.

confidentialinternalpublic

TrustTier

Minimum worker trust tier required to run the job, derived from its sensitivity at submit. Control-plane-assigned to workers; never self-reported.

known_providerowner_trusteduntrusted

JobStatus

Position in the job lifecycle state machine.

acceptedholdqueuedscheduleddispatchedrunningsucceededfailedinterruptedexpireddead_lettercancelled

BatchStatus

OpenAI batch lifecycle status.

validatingfailedin_progressfinalizingcompletedexpiredcancellingcancelled

SubmitJobRequest

FieldTypeDescription
model (required)stringWhat to run. An intent alias (e.g. `otium-medium`) or an exact catalog model id. Required. An alias is resolved to a concrete model server-side; an unresolvable value is rejected with 400.
otium OtiumIntentOptional intent extension — declare an outcome (task, quality floor, family) rather than only a model. OpenAI-compatible (stock clients ignore it).
tier TierSLA tier. Omit to default to `remnant`.
rushprioritystandardremnant
payload stringSmall inline request body (PoC). Production payloads live in object storage.
idempotency_key stringPer-tenant key making resubmission safe. A repeat returns the original job.
max_attempts integerMax execution attempts before dead-lettering. Non-positive values default to 3.
Default: 3
boundary BoundaryLocks the job to a residency boundary. Empty means unconstrained.
afapaccaeueu-demenasaukus
sensitivity SensitivityData-sensitivity class. Empty defaults to `internal` (trusted-only).
confidentialinternalpublic
max_tokens integerOutput-token ceiling. Bounds the up-front cost estimate the prepaid gate reserves; 0 uses a default ceiling. A chat-completion body that sets neither max_tokens nor max_completion_tokens is capped at 8192 output tokens when it runs.

OtiumIntent

The optional `otium` selection extension: declare an outcome instead of a model. Rung 1 routes on the `model` alias alone; these fields are carried for the measured router and planner (later rungs) and do not yet change the resolved model.

FieldTypeDescription
task stringThe task kind, e.g. extract | classify | summarize | generate | chat.
quality stringThe quality floor — the cheapest execution that meets it, e.g. good | high | best.
family stringModel-family constraint — auto (default) | qwen | gemma | glm | an exact model id.
allow_upgrade booleanOverrides the account's upgrade setting for this job. true lets it run on a warm, larger model at its own product's price; false keeps it on its own. Omitted takes the account setting, which is on by default.

Job

The durable record of one unit of deferred inference work.

FieldTypeDescription
id (required)string (uuid)
idempotency_key string
tenant (required)string
product stringThe sellable SKU the job was submitted under (billing keys on it). Empty for pre-product jobs.
model (required)stringThe concrete model the job runs on (dispatch/provisioning key on it).
status (required)JobStatus
acceptedholdqueuedscheduleddispatchedrunningsucceededfailedinterruptedexpireddead_lettercancelled
tier (required)Tier
rushprioritystandardremnant
deadline (required)string (date-time)SLA deadline; the job expires if not completed by this time.
boundary Boundary
afapaccaeueu-demenasaukus
sensitivity Sensitivity
confidentialinternalpublic
required_trust TrustTier
known_providerowner_trusteduntrusted
own_hardware_only booleanWhether the job runs only on the account's own workers (customer-hosted), waiting for them rather than running on Otium's capacity. Set when the job is created, from the account setting.
allow_upgrade booleanWhether the job may run on a warm, larger model at its own product's price. Set when the job is created, from the request or the account setting.
served_model stringThe model that served the job when it was upgraded onto a larger model; empty when it ran on `model`. Billing always keys on `product`.
run_id stringWorkflow run this job is an attempt of. Empty for an ordinary job. A workflow job is scheduled, leased and executed by exactly the same path as any other; these two fields are only how a completion finds its graph node.
node_key stringWorkflow node this job is an attempt of. Empty for an ordinary job.
attempts (required)integer
max_attempts (required)integer
last_error stringCategory/summary of the last failure. Never contains payload content.
payload string
result string
input_ref stringObject-storage key for the input when not stored inline.
result_ref stringObject-storage key for the result when not stored inline.
leased_by stringWorker id holding the job while running.
lease_expires_at string (date-time)
created_at (required)string (date-time)
updated_at string (date-time)
queued_at string (date-time)
scheduled_at string (date-time)
started_at string (date-time)
finished_at string (date-time)
content_purged_at string (date-time)When the retention policy deleted this job's payload and result. Absent while the content is held. Status, token counts and cost are kept regardless.
input_tokens integer
output_tokens integer
cached_tokens integer
cost_usd number
estimated_cost_usd number

FileObject

OpenAI representation of an uploaded or generated file.

FieldTypeDescription
id (required)string
object (required)string
file
bytes (required)integer (int64)
created_at (required)integer (int64)Creation time, Unix seconds.
filename (required)string
purpose (required)string
batchbatch_output

Upload

OpenAI's Upload object.

FieldTypeDescription
id (required)string
object (required)string
upload
bytes (required)integer (int64)
created_at (required)integer (int64)
filename (required)string
purpose (required)string
status (required)string
pendingcompletedcancelledexpired
expires_at (required)integer (int64)
file (required)FileObjectThe file a completed upload became; null until then.

UploadPart

OpenAI's Upload Part object.

FieldTypeDescription
id (required)string
object (required)string
upload.part
created_at (required)integer (int64)
upload_id (required)string

FileList

FieldTypeDescription
object (required)string
list
data (required)array of FileObject
first_id (required)string, nullableThe first item's id; null on an empty page.
last_id (required)string, nullableThe last item's id, the `after` for the next page; null on an empty page.
has_more (required)boolean

FileDeleted

FieldTypeDescription
id (required)string
object (required)string
file
deleted (required)boolean

CreateBatchRequest

FieldTypeDescription
input_file_id (required)stringId of an uploaded file with purpose `batch`, owned by the caller.
endpoint stringThe only endpoint supported today.
/v1/chat/completions
Default: /v1/chat/completions
completion_window stringOpenAI `24h` (default), the shorthands `1h` / `6h` / `7d` / `168h`, or an Otium tier name (`rush`, `priority`, `standard`, `remnant`).
Default: 24h
metadata map of stringUp to 16 string key/value pairs. The reserved key `boundary` locks every job in the batch to a residency boundary. A key a gateway adds on its caller's behalf (`otari_user_id`) does not count against the 16.

Batch

OpenAI representation of a batch. Unset timestamps serialize as null.

FieldTypeDescription
id (required)string
object (required)string
batch
endpoint (required)string
errors BatchErrorList
input_file_id (required)string
completion_window (required)string
status (required)BatchStatus
validatingfailedin_progressfinalizingcompletedexpiredcancellingcancelled
output_file_id string
error_file_id string
created_at (required)integer (int64)Unix seconds.
in_progress_at integer (int64), nullable
expires_at integer (int64), nullable
finalizing_at integer (int64), nullable
completed_at integer (int64), nullable
failed_at integer (int64), nullable
expired_at integer (int64), nullable
cancelling_at integer (int64), nullable
cancelled_at integer (int64), nullable
request_counts (required)RequestCounts
metadata map of string

BatchList

FieldTypeDescription
object (required)string
list
data (required)array of Batch
first_id (required)string, nullableThe first item's id; null on an empty page.
last_id (required)string, nullableThe last item's id, the `after` for the next page; null on an empty page.
has_more (required)boolean

RequestCounts

Per-batch progress tally.

FieldTypeDescription
total (required)integer
completed (required)integer
failed (required)integer

BatchErrorList

Non-fatal errors discovered during validation.

FieldTypeDescription
object (required)string
list
data (required)array of BatchError

RunStatus

A run's (or run set's) position. `accepted`: persisted, nothing evaluated yet. `hold`: withheld until the balance covers its reservation. `running`: at least one node is live (queued work held before a cold start still reads `running`; see `holds`). `parked`: waiting on an external node, so no budget accrues. Terminal: `succeeded`, `partial` (some outputs produced, a first-class result), `failed`, `expired`, `cancelled`.

acceptedholdrunningparkedsucceededpartialfailedexpiredcancelled

RunOutcome

Why a finished run ended as it did. `completed_with_skips` is a success: the graph's guards pruned the rest.

completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled

NodeStatus

`blocked`: waiting on upstream nodes. `ready`: rendered and queued for a worker. `running`: a worker has it. `parked`: an external node waiting for your resume. Terminal: `succeeded`, `failed`, `skipped`. Never count `skipped` as failure; read `disposition`.

blockedreadyrunningsucceededfailedskippedparked

TerminalReason

Why a node (or attempt) stopped.

okinvalid_outputexecution_failedcapacity_unavailabletimeoutguard_falseupstream_skippedupstream_failedbudget_exhaustedpark_expiredcancelledtool_timeouttool_errortool_refused

Disposition

`ok`: produced its output. `pruned`: the graph correctly chose not to run it (a guard was false, or an upstream was pruned). `degraded`: something prevented it from running. Aggregate on this, never on `skipped`.

okpruneddegraded

RunSetHold

One node's held work in a run set.

FieldTypeDescription
node_key (required)string
reason (required)HoldReason
gatheringprice
latest_start string (date-time)As on `Hold`.
runs (required)integerHow many of the set's runs are waiting at this node.

RunSetSummary

FieldTypeDescription
id (required)string
workflow_id (required)string
batch_id stringThe batch that created the set. Absent for a continuation.
continues_set_id stringThe set this one continues, when it is a continuation.
tier (required)Tier
rushprioritystandardremnant
status (required)RunStatus
acceptedholdrunningparkedsucceededpartialfailedexpiredcancelled
outcome RunOutcome
completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled
total (required)integer
completed (required)integer
failed (required)integer
execution_budget_seconds (required)integer (int64)The SLA bought, per run. Stops while a run waits on you.
expires_at (required)string (date-time)The wall-clock bound, separate from the execution budget.
created_at (required)string (date-time)
finished_at string (date-time)

RunSetList

FieldTypeDescription
run_sets (required)array of RunSetSummary
count (required)integer
next_cursor stringPass as `after` for the next page. Absent on the last page.

RunSet

FieldTypeDescription
id (required)string
workflow_id (required)string
plan_id (required)string
batch_id string
tier (required)Tier
rushprioritystandardremnant
status (required)RunStatus
acceptedholdrunningparkedsucceededpartialfailedexpiredcancelled
outcome RunOutcome
completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled
execution_budget_seconds (required)integer (int64)The SLA bought, per run. Stops while a run waits on you.
expires_at (required)string (date-time)The wall-clock bound, separate from the execution budget.
total (required)integer
completed (required)integer
failed (required)integer
counts (required)map of integerRuns per `RunStatus`, live.
holds (required)array of RunSetHoldQueued work held before it starts, by node. Empty when nothing is held.
bounds_reached (required)array of RunSetBoundsPer node, how many runs took an output that reached a `maxLength` or `maxItems` its `response_format` set. Constrained decoding stops a field at its limit, so such a field was usually cut short. Each attempt's `bounds_reached` names the field. Empty when no output reached one.
set_run SetRunRef
created_at (required)string (date-time)
finished_at string (date-time)

RunSetBounds

One node's count of outputs that reached a size bound.

FieldTypeDescription
node_key (required)string
runs (required)integer

SetRunRef

The run carrying a workflow's set-scope nodes. Absent when the workflow has none; no `id` and status `pending` until every item has finished.

FieldTypeDescription
id string
status (required)stringA `RunStatus`, or `pending` before the set run exists.
outcome RunOutcome
completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled

SetRunPending

A set whose items are still running, so its set run does not exist yet.

FieldTypeDescription
status (required)stringAlways `pending`.
items (required)object

RunSummary

FieldTypeDescription
id (required)string
run_set_id (required)string
custom_id stringThe input line's `custom_id`.
status (required)RunStatus
acceptedholdrunningparkedsucceededpartialfailedexpiredcancelled
outcome RunOutcome
completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled
budget_consumed_seconds (required)integer (int64)
parked_seconds (required)integer (int64)
cost_usd (required)number
created_at (required)string (date-time)
finished_at string (date-time)

RunList

FieldTypeDescription
run_set_id (required)string
runs (required)array of RunSummary
count (required)integer
next_cursor stringPass as `after` for the next page. Absent on the last page.

Run

FieldTypeDescription
id (required)string
run_set_id (required)string
custom_id string
status (required)RunStatus
acceptedholdrunningparkedsucceededpartialfailedexpiredcancelled
outcome RunOutcome
completedcompleted_with_skipsnode_failedbudget_exhausteddeadline_exceededpark_expiredcancelled
budget_consumed_seconds (required)integer (int64)The SLA clock, including the wait for capacity and excluding parked time.
parked_seconds (required)integer (int64)Time spent waiting on you at external nodes.
execution_seconds (required)numberTime workers spent on this run: each finished attempt from lease to finish, retries included. Attempts still running add nothing yet, and an inherited node counted in the run that produced it.
cost_usd (required)number
estimated_cost_usd (required)number
nodes (required)array of RunNode
created_at (required)string (date-time)
finished_at string (date-time)

RunNode

FieldTypeDescription
node_key (required)string
seq (required)integerThe node's position in the plan.
status (required)NodeStatus
blockedreadyrunningsucceededfailedskippedparked
terminal_reason TerminalReason
okinvalid_outputexecution_failedcapacity_unavailabletimeoutguard_falseupstream_skippedupstream_failedbudget_exhaustedpark_expiredcancelledtool_timeouttool_errortool_refused
disposition (required)Disposition
okpruneddegraded
output anyThe node's validated output. Downstream bindings read this.
error stringWhy a failed node failed, as its last attempt reported it.
rejected_output anyThe last output a validator rejected, on a node that ended `invalid_output`. Kept apart from `output` so a rejected value can never reach a downstream node.
inherited_from_run_id stringThe earlier run that produced this output, when a continuation carried it.
input anyAn external node's rendered park payload.
hold Hold
execution_seconds (required)numberThis node's finished attempts in this run, lease to finish, summed.
started_at string (date-time)When the node became ready, so it includes the wait for a worker.
finished_at string (date-time)

Verdict

A validator's result. Carries a code, a pointer and a constraint, never content.

FieldTypeDescription
ok (required)boolean
code string
pointer stringJSON pointer to the offending location, e.g. `/name`.
expected stringThe constraint that failed, e.g. `string`.

Attempt

FieldTypeDescription
id (required)string
attempt (required)integer
policy_step (required)integerWhich step of the node's attempt policy (model fallback) this was.
status (required)AttemptStatus
runningsucceededfailed
terminal_reason TerminalReason
okinvalid_outputexecution_failedcapacity_unavailabletimeoutguard_falseupstream_skippedupstream_failedbudget_exhaustedpark_expiredcancelledtool_timeouttool_errortool_refused
disposition (required)Disposition
okpruneddegraded
from_run_id stringSet when this attempt ran in an earlier run that a continuation carried from.
identity (required)AttemptIdentity
output anyWhat this attempt produced, accepted or rejected.
verdicts (required)array of VerdictThe validator chain's results, in order.
bounds_reached (required)array of BoundWhere this attempt's output, once accepted, reached a `maxLength` or `maxItems` its `response_format` set. Empty when it reached none or was not accepted.
input_tokens (required)integer
output_tokens (required)integer
cached_tokens (required)integer
cost_usd (required)number
started_at string (date-time)When the attempt was created and its job queued, not when a worker took it.
finished_at string (date-time)
leased_at string (date-time)When a worker took the job (its last lease, after a requeue). Absent until then.
execution_seconds (required)numberFrom the lease to the job finishing. 0 until it has.

NodeAttempts

FieldTypeDescription
run_id (required)string
node_key (required)string
status (required)NodeStatus
blockedreadyrunningsucceededfailedskippedparked
terminal_reason TerminalReason
okinvalid_outputexecution_failedcapacity_unavailabletimeoutguard_falseupstream_skippedupstream_failedbudget_exhaustedpark_expiredcancelledtool_timeouttool_errortool_refused
disposition (required)Disposition
okpruneddegraded
inherited_from_run_id string
final_attempt_id stringThe attempt whose output became the node's.
attempts (required)array of Attempt
count (required)integer
cost_usd (required)numberThe attempts' cost, summed.

ParkedRun

FieldTypeDescription
run_id (required)string
custom_id string
input anyThe external node's rendered input.
resume_token string
parked_at (required)string (date-time)

ParkedCohort

FieldTypeDescription
run_set_id (required)string
node_key (required)string
runs (required)array of ParkedRun
next_cursor stringPass as `after` for the next page. Absent on the last page.
count (required)integer

ResumeLineResult

FieldTypeDescription
custom_id (required)string
run_id string
ok (required)boolean
error stringWhy this line was rejected. Other lines are unaffected.
verdict Verdict

BulkResumeResult

FieldTypeDescription
results (required)array of ResumeLineResult
resumed (required)integer
rejected (required)integer

ResumeRequest

FieldTypeDescription
output (required)objectThe external node's output, checked by its validators.

ResumeOK

FieldTypeDescription
ok (required)boolean
true

ResumeRejected

FieldTypeDescription
error (required)string
verdict (required)Verdict

RerunSummary

FieldTypeDescription
node_key (required)string
reason TerminalReason
okinvalid_outputexecution_failedcapacity_unavailabletimeoutguard_falseupstream_skippedupstream_failedbudget_exhaustedpark_expiredcancelledtool_timeouttool_errortool_refused
runs (required)integer

RerunRequest

FieldTypeDescription
version integerThe workflow version to rerun against. 0 or absent is the latest published.
from (required)array of stringThe steps to rerun. They and every step downstream of them run again.
dry_run booleanCreate nothing; answer what the rerun would cover and cost.

RerunResult

FieldTypeDescription
run_set_id stringThe new run set. Absent on a dry run.
source_run_set_id (required)string
existing (required)booleanTrue when an identical earlier call created this rerun.
dry_run (required)boolean
runs (required)integerItems the rerun covers.
held_runs (required)integerRuns created `hold`, waiting on funds or the monthly spend cap.
rerun_steps (required)array of string
carried_steps (required)array of stringSteps whose recorded output is reused, at no charge.
excluded (required)array of objectSource items left out, by reason. Empty when none were.
estimated_cost_usd (required)numberThe p95 of what the rerun buys. Reused steps cost nothing.

Continuation

FieldTypeDescription
run_set_id (required)stringThe new set.
source_run_set_id string
existing (required)booleanTrue when a repeat call returned the continuation an earlier one created.
runs (required)integer
inherited_nodes (required)integerNodes carried over with their outputs, not bought again.
rerunning_nodes (required)integer
skipped_runs (required)integerSource runs not continued (already succeeded, or continued before).
held_runs (required)integerContinuation runs waiting on funds or the monthly spend cap. A continuation is a new purchase, admitted like a batch line on each run's reservation; a held run starts on its own once the account can cover it.
rerun (required)array of RerunSummaryWhat is being run again, by node and reason.

AssetStatus

`published`: runs may pin it. `deprecated`: new runs may not pin it, existing ones keep it. `purged`: its content is destroyed and its record kept.

publisheddeprecatedpurged

AssetBundleSummary

FieldTypeDescription
bundle (required)string
latest_version (required)integer
status (required)AssetStatus
publisheddeprecatedpurged
versions (required)integer
bytes (required)integer (int64)
updated_at string (date-time)

AssetBundleList

FieldTypeDescription
bundles (required)array of AssetBundleSummary
count (required)integer

AssetVersion

One version's metadata. Never its content.

FieldTypeDescription
id (required)string
bundle (required)string
version (required)integer
status (required)AssetStatus
publisheddeprecatedpurged
digest (required)stringDigest of the content, so identical publishes are recognised.
bytes (required)integer (int64)
assets (required)integerHow many assets the version supplies.
keys (required)integerHow many keys its keyed assets cover.
comment string
created_at (required)string (date-time)
published_at string (date-time)
purged_at string (date-time)

AssetVersionList

FieldTypeDescription
bundle (required)string
versions (required)array of AssetVersion
count (required)integer

AssetDetail

One version's metadata and its content.

FieldTypeDescription
id (required)string
bundle (required)string
version (required)integer
status (required)AssetStatus
publisheddeprecatedpurged
digest (required)string
bytes (required)integer (int64)
assets (required)objectThe content, in the form it was published: a string for a shared value, an object of key to string for a keyed one. Empty once purged.
keys (required)integer
comment string
created_at (required)string (date-time)
published_at string (date-time)
purged_at string (date-time)

AssetPublishRequest

FieldTypeDescription
bundle (required)stringThe bundle to publish a version of. Created on first publish.
comment stringA note kept with the version.
assets (required)objectAsset name to value: a string for one value shared by every run, or an object of key to string for one value per key.

AssetPublishResult

FieldTypeDescription
created (required)booleanFalse when the content matched the latest version and nothing was created.
version (required)AssetVersion

WebhookEvent

`run_set.completed` and `run_set.node_parked` fire once per run set (the default). `run_set.items_completed` fires once per run set too, when every item of a workflow with set-scope nodes has finished and its set run starts; subscribe to it by name. The `run.*` and `node.completed` events fire once per item and must be subscribed to by name. `batch.completed`, `batch.failed`, `batch.expired` and `batch.cancelled` fire once when a plain batch reaches that status (in the default subscription), named as OpenAI names them; a batch that runs a workflow fires `run_set.completed` instead.

run_set.completedrun_set.node_parkedrun_set.items_completedrun.completedrun.failedrun.partialrun.parkedrun.expirednode.completedbatch.completedbatch.failedbatch.expiredbatch.cancelled

WebhookEndpoint

A registered endpoint. Never carries the signing secret.

FieldTypeDescription
id (required)string
url (required)string
description string
events (required)array of WebhookEvent
enabled (required)boolean
created_at (required)string (date-time)
updated_at (required)string (date-time)
last_success_at string (date-time)
last_failure_at string (date-time)
last_error string
consecutive_failures (required)integer

WebhookEventInfo

FieldTypeDescription
event (required)WebhookEvent
run_set.completedrun_set.node_parkedrun_set.items_completedrun.completedrun.failedrun.partialrun.parkedrun.expirednode.completedbatch.completedbatch.failedbatch.expiredbatch.cancelled
per_run (required)booleanTrue when the event fires once per item rather than once per run set.
default (required)booleanTrue when an endpoint that names no events subscribes to it.

WebhookEndpointList

FieldTypeDescription
endpoints (required)array of WebhookEndpoint
count (required)integer
available_events (required)array of WebhookEventInfo

WebhookEndpointRequest

On update every field is optional, and a field left out is unchanged.

FieldTypeDescription
url stringAn https URL. Required to register.
description string
events array of WebhookEventEvents to subscribe to. Empty or absent on register means the set-level defaults.
enabled boolean

WebhookRegistration

FieldTypeDescription
endpoint (required)WebhookEndpoint
secret (required)stringThe signing secret. Shown here once; it cannot be retrieved later.
secret_note (required)string

WebhookDeleted

FieldTypeDescription
deleted (required)boolean
true

WebhookDelivery

FieldTypeDescription
id (required)string
endpoint_id (required)string
event (required)WebhookEvent
run_set.completedrun_set.node_parkedrun_set.items_completedrun.completedrun.failedrun.partialrun.parkedrun.expirednode.completedbatch.completedbatch.failedbatch.expiredbatch.cancelled
status (required)WebhookDeliveryStatus
pendingdelivereddead
attempts (required)integer
next_attempt_at string (date-time)When a pending delivery is retried next. Absent once it is final.
last_status_code integerThe HTTP status your endpoint last answered.
last_error string
created_at (required)string (date-time)
delivered_at string (date-time)

WebhookDeliveryList

FieldTypeDescription
deliveries (required)array of WebhookDelivery
count (required)integer

ToolEndpoint

A registered tool endpoint. Never carries the signing secret.

FieldTypeDescription
id (required)string
name (required)stringWhat a workflow's `tools.endpoint` names.
url (required)string
description string
created_at (required)string (date-time)
updated_at (required)string (date-time)

ToolEndpointList

FieldTypeDescription
endpoints (required)array of ToolEndpoint
count (required)integer
egress_ips (required)array of stringThe addresses tool calls come from, to allow on your endpoint's firewall. Empty when none are published for your deployment.

ToolEndpointRequest

To register, `name` and `url` are required. To update, send only `url` and/or `description`; sending `name` is refused.

FieldTypeDescription
name stringLowercase letters, digits, `-` or `_`.
url stringAn https URL.
description stringUp to 200 characters.

ToolRegistration

FieldTypeDescription
endpoint (required)ToolEndpoint
secret (required)stringThe signing secret. Shown here once; it cannot be retrieved later.
secret_note (required)string

DeviceStartRequest

FieldTypeDescription
device_name stringShown on the approval page and the Devices list, e.g. `otiumctl on build-01`. Optional.

DeviceStart

FieldTypeDescription
device_code (required)stringThe CLI's secret for polling. Never show it to the person.
user_code (required)stringThe code the person confirms in the portal.
verification_uri (required)stringThe portal page where the person approves the sign-in.
expires_in (required)integerSeconds until the codes expire.
interval (required)integerMinimum seconds between polls.

DevicePollRequest

FieldTypeDescription
device_code (required)stringFrom `POST /v1/auth/device`.

TokenRefreshRequest

FieldTypeDescription
refresh_token (required)string

TokenSignIn

A CLI sign-in, as the Devices list shows it.

FieldTypeDescription
id (required)string
name (required)stringThe device name the CLI sent.
last_four (required)stringThe last four characters of the current access token, for display.
created_ip (required)string
created_at (required)string (date-time)
last_used_at string (date-time)
revoked_at string (date-time)
expires_at string (date-time)When the sign-in ends regardless of use.

TokenResponse

An OAuth token response (RFC 6749 §5.1).

FieldTypeDescription
access_token (required)stringSend as `Authorization: Bearer <access_token>`.
token_type (required)string
Bearer
expires_in (required)integerSeconds until the access token expires. Renew it with the refresh token.
refresh_token (required)stringSingle-use. Each renewal returns a new one.
user_token (required)TokenSignIn

TokenErrorCode

invalid_requestauthorization_pendingslow_downaccess_deniedexpired_tokeninvalid_grant

TokenError

An OAuth error response (RFC 8628 §3.5, RFC 6749 §5.2).

FieldTypeDescription
error (required)TokenErrorCode
invalid_requestauthorization_pendingslow_downaccess_deniedexpired_tokeninvalid_grant
error_description (required)string

TokenRevoked

FieldTypeDescription
revoked (required)boolean
true

Account

FieldTypeDescription
tenant (required)string
name (required)string
email (required)string
plan (required)string
mfa_enabled (required)boolean
created_at (required)string (date-time)

APIKey

An API key's metadata. The secret is never part of it.

FieldTypeDescription
id (required)string
created_by stringThe account that created the key.
service booleanThe key belongs to a system (a pipeline, a deployment) rather than to the person who created it, so it counts as nobody's activity and outlives them.
name (required)string
prefix (required)stringAlways `sk-otium`.
last_four (required)stringThe last four characters of the secret.
created_at (required)string (date-time)
last_used_at string (date-time)
expires_at string (date-time)Absent when the key never expires.
revoked (required)boolean

APIKeyList

FieldTypeDescription
keys (required)array of APIKey
count (required)integer

APIKeyCreateRequest

FieldTypeDescription
name (required)string
expires_days integerDays until the key expires. Absent, it expires in 90 days. `0` is an explicit "never expires", which you have to ask for. Existing keys keep the expiry they were made with.
service booleanA key for a system rather than a person. Only an org's owners and admins may create one.

APIKeyCreated

A new key's metadata plus its secret, returned only this once.

FieldTypeDescription
id (required)string
created_by string
service boolean
name (required)string
prefix (required)string
last_four (required)string
created_at (required)string (date-time)
last_used_at string (date-time)
expires_at string (date-time)
revoked (required)boolean
secret (required)stringThe full key, `sk-otium-…`. Shown once; store it now.

APIKeyRevoked

FieldTypeDescription
id (required)string
revoked (required)boolean
true

WorkflowStatus

`published`: new runs may use it. `deprecated`: new runs may not; existing runs and reads are unaffected. `purged`: the document was erased; the version remains as a record.

publisheddeprecatedpurged

WorkflowSummary

FieldTypeDescription
name (required)string
description (required)string
latest_version (required)integer
status (required)WorkflowStatus
publisheddeprecatedpurged
versions (required)integerHow many versions exist.
updated_at string (date-time)

WorkflowList

FieldTypeDescription
workflows (required)array of WorkflowSummary
count (required)integer

WorkflowVersion

FieldTypeDescription
id (required)string
name (required)string
version (required)integer
status (required)WorkflowStatus
publisheddeprecatedpurged
digest (required)stringThe digest of the canonical document. Identical documents share it.
description (required)string
created_at (required)string (date-time)
published_at string (date-time)
purged_at string (date-time)

WorkflowVersionList

FieldTypeDescription
name (required)string
versions (required)array of WorkflowVersion
count (required)integer

WorkflowDetail

A version and its document.

FieldTypeDescription
id (required)string
name (required)string
version (required)integer
status (required)WorkflowStatus
publisheddeprecatedpurged
digest (required)string
description (required)string
created_at (required)string (date-time)
published_at string (date-time)
purged_at string (date-time)
document (required)stringThe canonical YAML. Empty once the version is purged.

WorkflowDocumentEnvelope

The JSON form of a document upload.

FieldTypeDescription
document (required)stringThe workflow document, as YAML text.

WorkflowDiagnostic

One compiler finding.

FieldTypeDescription
severity (required)WorkflowDiagnosticSeverity
errorwarn
code (required)stringA stable identifier for the kind of finding.
message (required)string
node stringThe node the finding is about, if any.
path stringWhere in the document, e.g. `tools.endpoint`.

PlanSummary

The headline figures for a compiled document.

FieldTypeDescription
nodes (required)integer
external_nodes (required)integer
tool_nodes (required)integer
depth (required)integerThe critical path's length in nodes.
critical_path (required)array of string
p50_duration_seconds (required)numberWall-clock critical path, parks included.
p95_duration_seconds (required)numberWall-clock critical path, parks included.
p95_execution_seconds (required)numberThe critical path with parks counted as zero. What the tier's execution budget is checked against.
est_cost_p50_usd (required)numberEstimated cost per run.
est_cost_p95_usd (required)numberEstimated cost per run.
cost_per_10k_usd (required)number`est_cost_p50_usd` for 10,000 runs.
affinity_groups (required)integer
barriers (required)integer
cache_groups (required)integer
errors (required)integer
warnings (required)integer
estimate_basis (required)PlanEstimateBasis
declaredassumed
declared_nodes (required)integerInference nodes that declared their token usage.
inference_nodes (required)integer
set PlanSetSummary

WorkflowCompileResult

The result of validating or publishing a document.

FieldTypeDescription
ok (required)booleanThe document compiled with no errors.
created (required)booleanPublishing created a new version. Always false for a validate or a replay.
name stringThe document's name, when it parsed.
plan Plan
digest string
diagnostics (required)array of WorkflowDiagnostic
summary PlanSummary
mermaid stringThe graph as a Mermaid diagram.
version WorkflowVersion

Plan

A compiled workflow version, the structure the scheduler runs from.

FieldTypeDescription
planner_version (required)integer
scopes (required)map of PlanScopePlans by scope. `item` always; `set` when the document has set-scope nodes.
asset_bundle stringThe asset bundle a run pins. Absent when the graph uses none.
assets array of stringThe asset names the graph reads.
est_cost_p50_usd (required)number
est_cost_p95_usd (required)numberPer item.
set_est_cost_p50_usd numberThe set scope's fixed cost, paid once per submission. Absent without a set scope.
set_est_cost_p95_usd numberThe set scope's fixed cost, paid once per submission. Absent without a set scope.
set_est_cost_per_item_p95_usd numberWhat each item adds to the set scope's cost. Absent without a set scope.
estimate_basis (required)PlanEstimateBasis
declaredassumed
declared_nodes (required)integer
inference_nodes (required)integer
tool_endpoint stringThe registered tool endpoint the run's tool nodes call.

WorkflowPlan

FieldTypeDescription
name (required)string
version (required)integer
planner_version (required)integer
plan (required)Plan
mermaid stringThe graph as a Mermaid diagram. Absent once the version is purged.
summary PlanSummary

WorkflowTestRequest

FieldTypeDescription
document (required)stringThe workflow document under test, as YAML text. Up to 1 MiB.
tests (required)stringThe test suite (a `*.test.yaml` file's contents), as YAML or JSON. Up to 1 MiB.
run stringRun only the cases whose name contains this.

WorkflowTestReport

FieldTypeDescription
passed (required)integer
failed (required)integer
cases (required)array of WorkflowTestCase

WorkflowTestCase

FieldTypeDescription
name (required)string
pass (required)boolean
failures array of stringEach difference from what the case expected. Absent when it passed.
run (required)WorkflowTestObserved

HealthOK

FieldTypeDescription
status (required)string
ok

HealthDegraded

FieldTypeDescription
status (required)string
degraded
database (required)string
down

NativeError

Native-surface error envelope (`POST /v1/jobs`, `GET /v1/jobs/{id}`).

FieldTypeDescription
error (required)string

OpenAIError

OpenAI-compatible error envelope used by the Files and Batch endpoints.

FieldTypeDescription
error (required)object

Send your first batch.

Otium is in beta. Leave your email and we’ll send you a link to create your account.

Free to try on our demo model. No credit card, no spam: we email you a link to finish.

Otium is in beta and open to everyone. Already have an account? Sign in.