POST/api/v1/flows/{flowId}/runs
Spawns a fresh sandboxed Claude-CLI container running this flow. If
prompt is provided, it’s sent as the initial message; otherwise the
flow’s pre-configured prompt (if any) is used.
Pass Idempotency-Key header (or idempotencyKey in the body) to
deduplicate retries within 24 hours.
Authentication
Requires a project API key — see Authentication.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
flowId | path | string | required | UUID of the flow to trigger. |
Idempotency-Key | header | string | optional | Deduplicate retries within 24 hours for this project. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | optional | Initial message sent to the agent. |
idempotencyKey | string | optional | |
callbackUrl | string uri | optional | HTTPS URL to receive the signed run.finished webhook. |
mcpServers | object | optional | MCP servers available to this run alone, isolated to its container. Lets one flow serve many tenants: mint a scoped token per run and pass it as a header, rather than rewriting the flow’s shared MCP artifacts before each trigger. The config is stored where no client can read it, delivered once at container start, and deleted on delivery. Remote transports only — http and sse. A stdio server would name a binary to execute in the container and is rejected. Cannot be combined with an idempotency key — see below. |
mcpMode | string (merge | replace) | optional |
appendSystemPrompt | string | optional | Appended to this run’s system prompt — framing that belongs to the run rather than the flow: which document is being edited, which tool to propose changes through, how to address the user. Appended, never replacing. The flow’s own instructions still apply; a caller wanting to replace them is describing a different flow. |
disallowedTools | array | optional | Tools withheld from this run. A real control, not a hint: a tool named here is absent from the session entirely, and this holds even though runs execute with permissions bypassed. Use it when a guarantee like “the model must not write directly” has to be enforced rather than merely asked for — a prompt is advisory, this is not. Names match the CLI’s own: Bash, Write, an MCP tool as mcp__<server>__<tool>, or a specifier like Bash(git:*). |
env | object | optional | Environment variables for this run’s agent process, and therefore for the MCP servers and tools it launches. This is the process environment, not the workdir’s .env file — .env is read by the flow’s own scripts, whereas anything configuring the agent or an MCP server must be inherited at spawn. Names the platform owns are rejected rather than ignored, so a typo fails loudly instead of leaving you believing a variable is set: anything beginning CLAUDE_, ANTHROPIC_, FLOW_, LD_ or DYLD_, and the exact names PATH, HOME, NODE_OPTIONS, NODE_PATH, SIGNED_TOKEN, SESSION_ID, MAIN_BACKEND_URL. These do not configure a run — they change what the platform is. |
files | array | optional | Files to seed the working directory with, stored before the container starts. This is the only correct way to seed a one-shot run. POST /runs/{runId}/files cannot do it: the prompt is delivered at creation, so the agent begins before you can inject, and the run id does not exist until the run does — there is no moment in between. Same shape and same limits as file injection, encoding included. .flowignore decides where each file goes, not whether it is accepted. An ordinary path becomes a flow file, stored and shared by every run of the flow. A path matched by .flowignore is instance-only: written into this run’s working directory before the container starts, preserved by its snapshot, and never stored as a flow file or pushed to git. Only the flow half counts against the per-flow storage limit. |
name | string | optional | Human-readable name for this run, shown in the dashboard. Without one it is displayed by its trigger — “API Run” — which is fine for one run and unhelpful across a hundred. |
labels | any | optional | Your own name/value pairs for this run. Stored verbatim, returned on every read, never interpreted. Safe to combine with Idempotency-Key — labels are descriptive, so unlike per-run configuration they do not make a replay dangerous. Note that a replay returns the original run and therefore its original labels; use PATCH /runs/{runId}/labels to change them. |
partialMessages | boolean | optional | Stream the model’s output as it is written, rather than one complete message at a time. Without it you still learn what is happening the moment it happens — an assistant event carries a tool’s name and arguments before the tool runs — but the prose of a reply arrives in one piece when the message finishes, and a long thinking pass is silent until it completes. With it, deltas arrive as stream_event on the stream, carrying Anthropic’s standard streaming shapes: message_start, content_block_start, content_block_delta (with a text_delta, thinking_delta or signature_delta), content_block_stop, message_delta, message_stop. Thinking streams too. Off by default: it is token-rate traffic through every subscriber, which is worth it for something a human watches type and wasted on an unattended run. The rendered output event is unaffected either way — deltas do not appear in it. |
Responses
| Status | Description |
|---|---|
200 | Idempotency hit — existing run returned. |
201 | Run created. |
400 | Request body or query parameters failed validation. |
401 | Missing, malformed, expired, or revoked API key. |
403 | Flow does not belong to this project. |
404 | Resource not found or not accessible to this project. |
409 | Self-hosted runner is offline. |
429 | Rate limit, concurrent cap, or monthly quota exceeded. |
Tag: Runs