Skip to content
Go To Dashboard

Executions API

These routes start and read runs of your deployed agents from your own server. The base URL is https://api.sapiom.ai. Send your API key in the x-api-key header.

Every route is scoped to the tenant of the API key. A run that belongs to another tenant answers 404, the same as a run that does not exist.

RoutePurposePermission
POST /v1/workflows/executionsStart a runorg.write
GET /v1/workflows/executionsList runsorg.read
GET /v1/workflows/executions/:idRead one runorg.read
GET /v1/workflows/executions/:id/spendRead one run’s costorg.read

org.write includes org.read. A key created without an explicit permission list has full access and can call every route here. A key without the required permission gets 403.

Execution IDs are numeric strings, for example "4821". Any other :id answers 400 with code: "invalid_execution_id".

POST /v1/workflows/executions

Body fieldTypeRequiredDescription
definitionIdstringyesThe deployed agent to run.
inputobjectyesInput for the entry step. Saved setting defaults are merged under it; your values win. The entry step’s inputSchema validates the result.
idempotencyKeystringnoUnique within your tenant, across all agents. A second start with the same key starts nothing and returns the run the key already started.

Response 201:

{ "status": "enqueued", "executionId": "4821" }
FieldDescription
statusenqueued for a new run. already_exists when idempotencyKey was already used.
executionIdThe new run, or the run that already used the key.
existingStatusOnly with already_exists: that run’s current status.

The response confirms the run was queued. It is not the run’s result; read the run until its status is terminal.

Errors: 400 for a missing definitionId, an input that is not an object, input nested too deeply, or input the entry step’s schema rejects. 404 when the agent does not exist in your tenant.

GET /v1/workflows/executions

Returns an array of runs, newest startedAt first.

Query parameterDescription
definitionIdOnly runs of this agent. A numeric ID; a value that is not numeric matches no run.
nameOnly runs of agents with this name. Names can repeat across forks, so prefer definitionId.
statusOne or more of running, paused, completed, failed, cancelled: comma-separated (status=running,paused) or repeated.
fromRuns started at or after this ISO 8601 time.
toRuns started at or before this ISO 8601 time. Applied only together with from.
limitPage size, 1 to 500. Default 100.
offsetRows to skip.

paused is a run waiting for a signal; there is no separate waiting status. To page through a period without new runs shifting the offsets, fix both from and to and increase offset by limit until a page comes back shorter than limit.

An unknown parameter, an unknown status, an empty status, a malformed date, or a limit or offset out of range answers 400.

Each row has these fields. Rows do not include input, output, or error; read one run for those.

FieldDescription
idThe execution ID.
name, definitionIdThe agent’s name and ID.
buildRunIdThe build the run executes.
statusrunning, paused, completed, failed, or cancelled.
currentStep, currentStepAttemptThe step in progress and its attempt number.
idempotencyKeyThe key the run was started with, or null.
pausedSignalName, pausedSignalCorrelationId, pausedUntilSet while the run is paused on a signal.
startedAt, finishedAtISO 8601 times. finishedAt is null until the run is terminal.
cost{ listUsd, billedUsd, ... } from a rollup that can lag, or null. Not final; use the spend route to bill.
versionA counter for updates to the run row. Not a build or release version.

GET /v1/workflows/executions/:id

Returns every list field except cost, plus:

FieldDescription
inputThe input the entry step received, after defaults were merged.
outputThe final output. Set when status is completed.
errorThe terminal error. Set when status is failed or cancelled.
stepsOne entry per step attempt, in order, with its input, output, error, and timing.
childrenRuns this run dispatched: { executionId, targetType, correlationId, status }.
parentExecutionIdThe run that dispatched this one, or null for a run you started.
rootExecutionIdThe top run of the dispatch tree. Equals id for a run you started.
triggerKindHow the run started: event, webhook, schedule, orchestration_dispatch, or null for an API start.

Values that look like secrets are redacted, and large values are truncated.

GET /v1/workflows/executions/:id/spend

{
"executionId": "4821",
"status": "completed",
"settled": true,
"usage": [
{ "meter": "llm.output_tokens.medium.standard", "quantity": 1840, "unit": "tokens", "listValueUsd": "0.0276" },
{ "meter": "sandbox_compute_gbs", "quantity": 412.5, "unit": "gb_seconds", "listValueUsd": "0.004125" }
],
"listValueUsd": "0.031725",
"billedUsd": "0"
}
FieldTypeDescription
executionIdstringThe run.
statusstringThe run’s status, with the same values as GET /v1/workflows/executions/:id.
settledbooleantrue once the figures below will not change. See Finality.
usagearrayOne line per meter the run consumed, highest list value first, unpriced lines last.
usage[].meterstringA stable meter key.
usage[].quantitynumberNet units consumed, in unit.
usage[].unitstring or nullThe meter’s unit, for example tokens, gb_seconds, or requests.
usage[].listValueUsdstring or nullThe line’s value at your list price, as a decimal string. null when the meter has no USD price; an unpriced line is never reported as "0".
listValueUsdstring or nullThe sum of the priced lines. "0" for a run with no usage. null only when every line is unpriced.
billedUsdstringWhat your organization was charged for this run in metering charges: settled and pending charges for the run, plus its pro-rata share of any streamed-overage charge. "0" for usage inside your plan’s included quota. Per-call x402 payments are not included.

Decimal strings carry up to 18 decimal places. Sum them with a decimal type, not floating point.

The response also contains fields used by the Sapiom dashboard (compute, capability, subtree, llm, totalUsd, organizationId, tenantId). They are not part of this contract and can change; read the fields in the table above.

The figures cover this run only. Runs it dispatched have their own spend; find them in children on GET /v1/workflows/executions/:id.

Every meter except sandbox compute (sandbox_compute_gbs) is recorded by the time the run ends. Sandbox compute is reported by the sandbox provider after the sandbox shuts down. Measured over production runs, it arrived a median of 40 to 55 minutes after the run, within about 3 hours for 99% of runs, and never later than about 6 hours.

settled is true when all of these hold:

  • the run is completed, failed, or cancelled;
  • none of its sandboxes is still running;
  • none of its charges is still pending;
  • 8 hours have passed since the later of the run’s finish and its last sandbox shutdown.

The 8-hour wait applies to every run, including runs that appear to use no sandbox. If Sapiom cannot read the run’s metering, settled is false.