Orchestrations

Start an orchestration run

Creates a new run for the orchestration named by orchestration_id. By default the run executes durably in the background: the response returns immediately with status "queued" (a worker then claims it and moves it to "running") and progress is observed via get-orchestration-run or run lifecycle webhook events (orchestration_runs.started/awaiting_input/completed/failed). Delay and poll waits park the run as "sleeping" and are woken by a background scheduler, surviving restarts. Pass wait=true to block until the run reaches a terminal or awaiting_input state.

post/v1/projects/{project_id}/orchestration-runs

Request

  • Base URL: https://api.naturali.ai
  • URL: https://api.naturali.ai/v1/projects/{project_id}/orchestration-runs
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)

Headers

Idempotency-Keystring

The request's deduplication key. Equivalent to idempotency_key in the request body; sending both with different values is 400 VALIDATION_FAILED. A non-empty string of at most 255 characters.

Request body

orchestration_idstring required

Orchestration to run (orch_...).

inputobject

Initial state for the run (merged with orchestration defaults).

tool_contextobject

Key-value pairs forwarded as X-Naturali-Context-<key> headers on every http and mcp tool call made by an agent node of this run — including the agents of any child run a loop or sub_orchestration node starts. The header name is X-Naturali-Context- plus the key verbatim; no character is re-cased.

The bag is stored on the run and re-read on every step, so it survives an awaiting_input pause, a sleeping wait, a background worker drive and a crash redrive. It is write-only: a run is a record every principal who may read runs can read, and a credential in it is not theirs to see, so it is never returned on one. It also does not outlive the run: reaching a terminal status (completed, failed, cancelled or expired) clears it. A key that is not a valid HTTP header name, or two keys that map to the same header, are rejected with 400 INVALID_TOOL_CONTEXT_KEY and no run is created.

The reserved identity keys (session_id, actor_id, actor_external_id) are stripped at generation time — a caller cannot address them from here.

metadataMetadataBag

Caller-owned annotations on a resource, stored as the object they were written as: the types a value was written with are the types a read returns, so a filter can ask an ordering question about a number. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.

No key is reserved, and that is the point: every piece of state the platform owns lives in its own typed column, so nothing written here reaches platform state. The platform never reads the bag — it is not an IAM context, not a policy input and not part of a prompt — which is what separates it from a tag bag.

idempotency_keystring

Deduplication key, unique within the project, that makes a retry of an ambiguous failure safe. The first request under a key starts the run and answers 201; any later request carrying the same key answers 200 with that same run, whatever state it has reached — including a retry that arrives while the original is still running.

The key is claimed by the run record and stays claimed for as long as the record exists, so it never silently expires and lets a second run through.

orchestration_id, input, tool_context and metadata are the request the key names: reusing a key with any of them changed is 409 IDEMPOTENCY_KEY_REUSED rather than a replay of a run that does something else. wait is not part of that comparison — it says how the caller waits, not what the run is — so a retry may flip it.

waitboolean

When true, block until the run reaches a terminal (completed/failed) or awaiting_input state and return the settled run. When false (default), return immediately with status "queued" and execute the run in the background.

Example request

{
  "orchestration_id": "orch_V1StGXR8Z5jdHi6B",
  "tool_context": {
    "ocaToken": "eyJhbGciOiJIUzI1NiJ9.abc"
  },
  "metadata": {
    "author": "John",
    "revision": 2
  },
  "idempotency_key": "dispatch-2026-09-18-activation-42"
}

Response

Duplicate request — the run the idempotency_key already names is returned and no second run is started.

idstring required

Public ID (run_...).

orchestration_idstring required

Public ID of the parent orchestration.

orchestration_versioninteger nullable

The orchestration version this run executes, fixed when the run started. Every later step of the run — the first drive, a wake from sleeping, a human or approval resume, a redrive after a crash — resolves the graph from this version, so editing the orchestration never re-shapes a run already in flight. Fetch the graph it names at GET /v1/projects/{project_id}/orchestrations/{orchestration_id}/versions/{version}.

Null for runs created before pinning existed, which execute the live graph.

project_idstring required

Public ID of the owning project.

status'queued' | 'running' | 'sleeping' | 'awaiting_input' | 'completed' | 'failed' | 'cancelled' | 'expired' required

Run lifecycle state. queued awaits a worker; running is actively executing; sleeping is parked on a delay/poll wait (no worker); awaiting_input is parked on a human node; completed/failed/ cancelled are terminal; expired is a wait that passed its deadline.

stateobject required

Current accumulated state.

active_nodesstring[] required

Node IDs currently active.

artifactsobject required

Map of node ID to output artifact.

trace_idstring nullable
inputobject nullable

Initial input provided at run creation.

metadataMetadataBag

Caller-owned annotations on a resource, stored as the object they were written as: the types a value was written with are the types a read returns, so a filter can ask an ordering question about a number. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.

No key is reserved, and that is the point: every piece of state the platform owns lives in its own typed column, so nothing written here reaches platform state. The platform never reads the bag — it is not an IAM context, not a policy input and not part of a prompt — which is what separates it from a tag bag.

idempotency_keystring nullable

The deduplication key the run was started under, unique within the project and claimed for as long as the run record exists. Null for a run started without one, which every platform-started run is.

parent_orchestration_run_idstring nullable

The run whose node started this one — set only on a child a loop or sub_orchestration node spawned, null for a run a caller started. A child is its own run with its own usage events, so this is what makes a delegated run's spend attributable to the run that ordered it.

parent_node_idstring nullable

The node within parent_orchestration_run_id that started this run. Null when parent_orchestration_run_id is null.

orchestration_run_depthinteger

loop / sub_orchestration edges between this run and the run a caller started: 0 for a caller-started run, one more than its parent's for a child. Starting a child past the effective bound — the smaller of the deployment's MAX_ORCHESTRATION_RUN_DEPTH (default 10) and the project's max_orchestration_run_depth — is refused with ORCHESTRATION_RUN_DEPTH_LIMIT, which fails the run that tried to descend. That bounds a graph whose sub_orchestration node names itself, directly or through a cycle of two graphs, which the intra-graph cycle check cannot see.

outputobject nullable

What a completed run returns: the orchestration's output_mapping evaluated over the final state, or, when it declares none, the terminal node artifacts keyed by node id. Null unless the run completed.

pause_requested_atstring date-time nullable

When an operator pause was requested, or null when none is in force. Independent of status: a running run keeps running until its next checkpoint, and a run parked on a node keeps that node's required_action.

pause_reasonstring nullable

The reason supplied with the pause, when one was.

started_atstring date-time nullable
completed_atstring date-time nullable
created_atstring date-time required
updated_atstring date-time required

Example response

{
  "orchestration_version": 3,
  "error": {
    "code": "AI_PROVIDER_ERROR",
    "message": "Provider returned 402: insufficient credits"
  },
  "metadata": {
    "author": "John",
    "revision": 2
  },
  "idempotency_key": "dispatch-2026-09-18-activation-42"
}

Changes

No recorded changes to this operation across all 1 revision of this API.