Runs, Tasks, and Observe API
API surface for SOIT runtime state, task tracking, trace inspection, cost reconciliation, observe views, and ledger exports.
Runs, tasks, and observe APIs expose runtime state and execution evidence from the runtime ledger.
Prefixes
/api/v1/runs
/api/v1/tasks
/api/v1/observe
/api/v1/exportsRuns endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | / | List runs with filters and pagination, including source and api_key_id |
| GET | /{run_id} | Run detail with steps, artifacts, costs |
| GET | /{run_id}/evidence | The run's evidence bundle as a deterministic zip; digest in X-SOIT-Evidence-SHA256 |
| GET | /{run_id}/stream | Live run event stream |
| GET | /trace/{trace_id} | All runs for a trace |
| GET | /steps, /steps/metrics | Run steps and step metric summaries |
| GET | /audits | Gateway audit log entries |
| GET | /costs/summary, /costs/by-day / by-subject / by-mode / by-provider / by-model | Cost attribution rollups, filterable by source and api_key_id |
| GET | /costs/entries | Cost entries oldest first, paged with page_token and page_size (at most 500); until is inclusive. New in v1.6.0: the filters and row fields below |
| GET | /costs/reconciliation | New in v1.6.0: the ledger's side of a bill check for the half-open window [since, until), with optional group_by |
| GET | /export | Export run data |
Cost reconciliation
New in v1.6.0. /costs/entries and /costs/reconciliation take the same filters. Workspace readers can call both, as they can the other /costs reads.
| Query parameter | Filters by |
|---|---|
since, until | When the entry was written |
run_id | One run |
api_key_id | The run's API key |
user_id | The run's member or service principal |
source | The run's source, platform or gateway |
model_ref, provider_slug, tool_ref | The entry's model, provider, or tool |
source_port, operation | The kernel port that recorded the entry (such as llm or tools) and its operation (such as chat, embed, or invoke) |
currency | The entry's currency |
pricing_status | priced, estimated, free, or unpriced |
upstream_id, upstream_request_id | The provider's response id or request id |
Each /costs/entries row adds its run's api_key_id, user_id, and run_source, its pricing_status, its unpriced_reason when unpriced, and the provider's upstream_id and upstream_request_id when the provider gave them.
/costs/reconciliation answers:
| Field | Meaning |
|---|---|
since, until | The window, [since, until) |
entry_count, status_counts | Entries in the window, and per pricing status |
amounts | Priced total per currency, estimated amounts included; currencies are never added together |
estimated_amounts | The part of amounts computed from estimated usage |
unpriced_reasons | Unpriced entries per reason; they are never counted as zero |
group_by, groups, groups_truncated | With group_by (model, provider, tool, api_key, user, source, operation, or day), one row per value and currency with entry_count, amount, estimated_count, unpriced_count, and total_tokens; unpriced entries form a row of their own; at most 500 rows |
external_reconciliation | Always not_performed: the provider's bill is not read |
See Checking costs against a bill.
Tasks endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | / | List tasks with pagination |
| GET | /workbench, /workbench/items | Task queue views for the UI |
| GET | /{task_id} (+ /handling) | Task detail and handling state |
| POST | /{task_id}/cancel / /resume / /retry | Task control |
Observe endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /dashboard | Workspace observe dashboard |
| POST / GET | /approvals (+ /{approval_id}) | Open and list approval requests; filter by status, run_id, task_id |
| POST | /approvals/{approval_id}/resolve | Decide a request: approved, rejected, or canceled, with an optional note |
| POST | /approvals/{approval_id}/delegate | Hand a pending request to another member who can decide |
| GET | /approvals/{approval_id}/decisions | The request's history: decisions, closings, and delegations |
| POST / GET | /feedback | Feedback records |
| GET | /runs/{run_id}/replay | Assembled replay evidence for one run |
Approvals
A request carries status (pending, approved, rejected, canceled, or expired), assignee_user_ids, assignee_roles, expires_at, and, for the caller, can_decide, can_cancel, and assigned_to_me, worked out by the rules the server enforces.
| Status | When |
|---|---|
403 | The caller may not decide, cancel, or delegate this request |
409 | The request is already closed with a different decision, or is past its deadline |
New in v1.7.0: assignees, deadlines, /delegate, /decisions, the expired status, and the per-caller fields. See Approvals.
Exports endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /{kind} | Stream one kind of ledger record (runs, steps, costs, audit, events) created in [since, until), with format=jsonl or csv |
Notes
- Cost rollups (
by-subject,by-model,by-provider) power workspace cost attribution without external billing exports. - The replay endpoint returns the same assembled timeline the run detail page renders.
- Evidence bundles and ledger exports (since v1.3.0) use the versioned ledger contract. Exports cover at most 92 days per request, take a workspace owner or admin, carry the contract version in
X-SOIT-Ledger-Schema, and are written to the audit ledger asledger.exported. See Evidence and Exports. - New in v1.6.0: the ledger contract is version
1.1, whose cost records may carry the optionalupstream_idandupstream_request_id. - Since v1.5.0, each run on
GET /andGET /{run_id}carriescost_amountandcost_currency: the sum of its priced cost entries in their currency, or null when nothing was priced or the entries span more than one currency.