surface

Runs, progress and cancellation.

Submit API runs from saved or inline graphs, observe their lifecycle, cancel work, recover uncertain submissions, and retain the outputs you need.

Written for
Developers executing workflows through the REST API.
You need
An API key with runs:execute to create or cancel runs and runs:read to observe them
Interactive API reference Explore endpoints, request schemas and responses. Opens in a new tab

A public API run is one asynchronous execution of a graph. POST /api/v1/runs returns 202 Accepted with a run record, rather than waiting for the final result. Store its id so you can observe that attempt without submitting the work again. For canvas controls, use Runs in Studio.

All paths below are relative to /api/v1. Creating and canceling require runs:execute; reading a run or its events requires runs:read. Runs are account-owned, not restricted to the individual API key that created them. Another suitably scoped key for the same owner can read the run. Station visitor runs are exposed through the Station rather than these run routes.

Track work after the request returns

Keep a run receipt until its outcome and files are known.

Create work once from a saved project or inline graph and retain its run identity. Inspect queued, running and terminal states plus any available results. Cancel requests do not reverse provider work. Applying outputs is a separate guarded write for a succeeded saved-project run: use expectedVersion equal to run.projectVersion while the project still matches. Public run details expose source identifiers, not a retrievable graph snapshot body.

Only the succeeded branch of a saved-project run reaches guarded project application. Failed and canceled branches retain available evidence. Inline execution has no saved project to apply to.

Submit a precise request

Provide exactly one source:

Source Request fields Targeting
Saved project projectId Explicit targetNodeIds, or the saved graph's execution configuration when omitted
Transient inline graph graph At least one targetNodeIds entry is required

Use explicit targets when your application needs predictable intent. An inline graph run does not create a saved project. The server snapshots the graph document before dispatch, so subsequent project edits do not change that attempt's graph. Referenced files and external services still have to be available; the snapshot is not a promise to archive those dependencies.

inputOverrides are keyed by node instance ID, then input pin name:

{
	"projectId": "project_example",
	"targetNodeIds": ["prompt_node"],
	"inputOverrides": {
		"prompt_node": {
			"inputPrompt": { "type": "string", "value": "a lighthouse at dusk" }
		}
	}
}

The IDs and pin names must exist in your graph; this example is illustrative. Supported value tags are string, number, boolean, json, file, and null. A file value uses fileId instead of value. These are transport tags, separate from canvas pin types. Overrides affect this run without editing the saved project; persistInputOverrides: true is currently unsupported. See Projects and graph documents for graph structure and validation.

Retry submissions safely

Use Idempotency-Key on supported submission endpoints. Keep the same key and same request when recovering from an uncertain network result. Changing the request needs a different logical submission; reusing a key with conflicting content is an error.

An idempotency replay can return the original accepted response. Read the run detail to learn its current status. A key is not an unlimited promise that every failed, expired, or canceled job can be repeated without cost. Inspect the recorded run before deciding to start a new attempt.

Follow the lifecycle

Use GET /runs/{id} for current status and results:

Status Meaning
accepted A validated run record exists and work is being dispatched.
queued Execution has been claimed or queued; completion is still pending.
running The execution layer is working on the graph.
succeeded The attempt finished successfully; inspect its outputs.
failed The attempt ended in error; inspect error and events.
canceled The attempt stopped; do not assume it produced every requested output.

The last three states are terminal. A client polling slowly can miss short intermediate states. Failure or cancellation can happen before execution starts.

For detailed observation, poll GET /runs/{id}/events or stream GET /runs/{id}/events/stream using Server-Sent Events. Events include an id, runId, type, and createdAt; nodeId, progress, and message are optional. Types include run.accepted, node.progress, and node.log. Progress, when present, is between 0 and 1.

Polling returns data, nextCursor, and hasMore. Treat cursors as opaque. Resume SSE with the last SSE id in Last-Event-ID, or the cursor query parameter. Reuse a cursor only for the same run and API key owner that issued it.

Use structured error information and retain the run ID for support. Back off after rate limiting and avoid unbounded polling loops.

Request cancellation

POST /runs/{id}/cancel returns the updated record. If the run is still accepted or queued, cancellation makes it terminal immediately. If it is running, the request sets cancelRequested and the execution layer attempts to stop it. Keep observing the final status: cancellation can race with completion, and it cannot recall provider work already accepted externally.

Canceling an already canceled run returns that record. A succeeded or failed run cannot be canceled and returns a conflict. Cancellation is not a refund guarantee and may leave partial outputs.

Read the cost

Terminal records report creditsUsed when reliable accounting is available. creditsUsedMicrocredits is the exact amount in millionths of a credit, encoded as a string. The optional spend summary breaks usage down by node, provider, and charge type.

creditsUsed is null while active. It can also be null on a terminal run when a reliable summary is unavailable. Treat null as unknown, never as zero. A failed or canceled attempt may still have incurred charges. These fields describe actual recorded usage, not a price estimate for another attempt.

Apply results to a saved project

A run's outputs and a saved project's contents are separate. To retain the server-owned outputs of a succeeded saved-project run in that project, call POST /runs/{id}/apply-to-project. Inline runs cannot use this operation. The key needs all three scopes: runs:read, projects:write, and graphs:write.

Send expectedVersion equal to the run's projectVersion. You may supply an outputKeys subset; omit it to apply all recorded outputs. The endpoint accepts output selection, not client-supplied output values. Use an Idempotency-Key for a retryable application request.

If the saved project has changed since the run was created, application fails with a conflict instead of overwriting newer work. Inspect the current graph and rerun the intended version before applying results. A successful application returns the new project version, appliedOutputs, and outputKeys.

Keep output files

Use the public file workflow to upload or register supported inputs, then pass their file IDs. Result metadata can supply a short-lived download URL. Download what your application needs before it expires, or request a fresh authorized download through the file API.

Check ownership and any external-user guards on file references. A bare file ID is not proof that an application user should have access to that file. Run retention, library retention, and a downloaded copy are separate lifecycles.

The API reference (opens in a new tab) defines the current request fields, response schemas, errors, and limits.

Preserve the attempt and its snapshot

Accept: POST /runs returns an attempt ID and snapshots its source; it is not the final result. Observe: use that run's status/events and distinguish succeeded, failed, or canceled with unknown cost kept unknown. Apply: server-recorded outputs can be applied through a separate version-guarded action where eligible. Temporary URLs and saved-project state are different.

Checks and next steps

Saved-project run submission loads the project and retains an execution snapshot internally. It does not accept a document-write-style expectedVersion guard. Keep the returned sourceType, projectId, projectVersion and targets for provenance. Public run details do not return the snapshot body or a snapshot download route, and projectVersion is not a certificate of exact bytes during concurrent writes.

For caller-controlled source, retain and submit a supported explicit inline graph. That still does not freeze provider implementations, external services or file lifetimes. A previous saved-project read does not lock submission.

Applying outputs later is a separate version-guarded action. It requires a successful saved-project run, the necessary write scopes, and a compatible unchanged project context. A run result, a temporary media URL, a saved graph, and outputs adopted back into that graph are distinct facts.

If output application reports an unresolved or unavailable project save state, preserve the result and local work. Follow guarded project recovery instead of treating every refusal as a retryable stale version.

For upload and retention contracts see Files and outputs. For an uncertain submission, inspect the original run with its ID and preserve the same logical retry key before considering another paid attempt.

Last reviewed against Kaitoi on 24 October 2026. View this page as Markdown

Type at least two characters.