API deployment

Call a deployed workflow at POST /api/v2/workflows/{workflow-id}/execute. Choose a complete JSON result, an SSE stream, or an async run receipt.

Deploy the workflow

You need workspace Admin access and the applicable deployment permission. Test with Run, then open Deploy → General and click Deploy or Update. Deployment covers versions, comparison, rollback, and undeploying.

Ordinary API calls use the active snapshot. Editing the draft does not change that version. Deploy an update before expecting a normal API call to use your changes.

Authentication

Send a valid Sim API key in X-API-Key, or use a supported OAuth access token. Deployed workflow execution requires access to the workflow's workspace; OAuth callers also need the operation's api:write scope. See API authentication.

Generate keys in Settings → Sim API keys or Deploy → API → Generate API Key. Keep the key available to your application as SIM_API_KEY.

API info and public access

Open Deploy → API → Edit API Info to set a description and choose API Key or Public access. API-key access is the default.

A public endpoint lets an anonymous caller run the deployed workflow. Restrict what input can do and what output reveals before enabling it. Public access is subject to deployment and organization policy; anonymous callers cannot start async or manual draft runs.

Make a call

Put named Start inputs inside the request's input value. For a field named message:

curl -X POST 'https://www.sim.ai/api/v2/workflows/{workflow-id}/execute' \
  -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"input":{"message":"Summarize this article"}}'

The API tab offers cURL, Python, JavaScript, and TypeScript examples. Replace example identifiers and supply your own key before calling them.

Execution modes

Synchronous

The default mode waits for the run to settle:

curl -X POST 'https://www.sim.ai/api/v2/workflows/{workflow-id}/execute' \
  -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"input":{"message":"Summarize this article"}}'
import os
import requests

response = requests.post(
    "https://www.sim.ai/api/v2/workflows/{workflow-id}/execute",
    headers={"X-API-Key": os.environ["SIM_API_KEY"]},
    json={"input": {"message": "Summarize this article"}},
)
response.raise_for_status()
print(response.json())
const apiKey = process.env.SIM_API_KEY
if (!apiKey) throw new Error('Set SIM_API_KEY')

const response = await fetch('https://www.sim.ai/api/v2/workflows/{workflow-id}/execute', {
  method: 'POST',
  headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
  body: JSON.stringify({ input: { message: 'Summarize this article' } })
})
if (!response.ok) throw new Error(`HTTP ${response.status}`)
const result = await response.json()
process.stdout.write(JSON.stringify(result))

V2 returns a run resource in data, including runId, workflowId, status, output, blockOutputs, error, and timing fields. Check data.status: a workflow that ran and failed can return HTTP 200 with status: "failed". An HTTP error instead describes a rejected request or a service failure.

A Response block selects the workflow result, which remains inside data.output. It cannot override the v2 endpoint's HTTP status, headers, or envelope.

A synchronous caller can request Accept: application/x-ndjson to receive heartbeat frames while waiting, followed by a type: "final" frame containing the same run resource. This is distinct from Agent token streaming with stream: true.

Streaming

Set stream: true and use selectedOutputs to select fields. Select outputs in the API tab groups fields by block; content from an Agent is a common choice.

Selectors use a stable block ID or normalized block name followed by a field path, such as agent.content for a block named Agent. Nested paths and reachable child-workflow selectors are also supported; see Execute workflow.

For live answer tokens, send X-Sim-Stream-Protocol: agent-events-v1 and handle chunk_reset. Without that header, answer text arrives after a final model turn settles. The header alone does not expose thinking or tool events.

curl -N -X POST 'https://www.sim.ai/api/v2/workflows/{workflow-id}/execute' \
  -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'X-Sim-Stream-Protocol: agent-events-v1' \
  -d '{"input":{"message":"Write a long essay"},"stream":true,"selectedOutputs":["agent.content"]}'
import os
import requests

with requests.post(
    "https://www.sim.ai/api/v2/workflows/{workflow-id}/execute",
    headers={
        "X-API-Key": os.environ["SIM_API_KEY"],
        "X-Sim-Stream-Protocol": "agent-events-v1",
    },
    json={
        "input": {"message": "Write a long essay"},
        "stream": True,
        "selectedOutputs": ["agent.content"],
    },
    stream=True,
) as response:
    response.raise_for_status()
    for line in response.iter_lines():
        if line:
            print(line.decode())
const apiKey = process.env.SIM_API_KEY
if (!apiKey) throw new Error('Set SIM_API_KEY')

const response = await fetch('https://www.sim.ai/api/v2/workflows/{workflow-id}/execute', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json',
    'X-Sim-Stream-Protocol': 'agent-events-v1'
  },
  body: JSON.stringify({
    input: { message: 'Write a long essay' },
    stream: true,
    selectedOutputs: ['agent.content']
  })
})
if (!response.ok) throw new Error(`HTTP ${response.status}`)
if (!response.body) throw new Error('Response body is missing')

const reader = response.body.getReader()
const decoder = new TextDecoder()
try {
  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    process.stdout.write(decoder.decode(value, { stream: true }))
  }
} finally {
  reader.releaseLock()
}

These examples print raw SSE for inspection. For an application, parse frames, accumulate answers per blockId, and honor resets and terminal errors using the stream reference client.

Streaming agent thinking and tool calls

Add independent includeThinking and includeToolCalls flags:

curl -N -X POST 'https://www.sim.ai/api/v2/workflows/{workflow-id}/execute' \
  -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'X-Sim-Stream-Protocol: agent-events-v1' \
  -d '{"input":{"message":"Research this topic"},"stream":true,"selectedOutputs":["agent.content"],"includeThinking":true,"includeToolCalls":true}'

Both flags default false. Enabling either without stream: true and the protocol header returns 400. Tool lifecycle frames contain names and status; full tool arguments/results can appear in the authenticated API's terminal envelope. Thinking support varies by model. See Agent stream events for the contract.

Asynchronous

Set async: true to receive HTTP 202 with a run ID and status URL instead of holding the connection open:

curl -X POST 'https://www.sim.ai/api/v2/workflows/{workflow-id}/execute' \
  -H "X-API-Key: $SIM_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"input":{"message":"Process this dataset"},"async":true,"executionTimeoutSeconds":3600}'
{
  "data": {
    "runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
    "statusUrl": "https://www.sim.ai/api/v2/workflows/{workflow-id}/runs/c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74"
  }
}

Async execution requires an API key or OAuth token and uses the deployed version. It cannot be combined with stream, manual draft execution, partial-run options, or streaming/output-shaping options such as selectedOutputs and includeThinking.

executionTimeoutSeconds accepts an integer from 1 to 604800 and is supported only with async: true. The effective limit is the smaller of that value and the account policy; it cannot extend the policy. Your HTTP client's timeout is separate.

Poll the returned run URL, requesting output when needed:

curl 'https://www.sim.ai/api/v2/workflows/{workflow-id}/runs/{runId}?includeOutput=true' \
  -H "X-API-Key: $SIM_API_KEY"

A completed response includes the result when requested:

{
  "data": {
    "runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
    "workflowId": "{workflow-id}",
    "status": "completed",
    "startedAt": "2026-10-13T12:00:01.000Z",
    "endedAt": "2026-10-13T12:00:05.000Z",
    "durationMs": 4000,
    "output": { "result": "..." }
  }
}

Execution status values

StatusMeaning
queuedWaiting to be picked up
pendingDurable record exists; execution has not started
runningExecuting
pausedWaiting for a resume condition or submitted input
redactingFinished execution; output is still being scrubbed
completedFinished successfully
failedFailed; inspect error
cancelledCancelled

Stop polling on completed, failed, or cancelled. A paused Human run requires submitted input; a time pause can resume automatically. See Human and Wait. Resuming an originally streaming run through the v2 resume endpoint returns an async receipt, not an SSE continuation.

Select outputs and handle large values

selectedOutputs can project smaller fields. For a synchronous v2 call, selected values appear in data.blockOutputs, separately from data.output.

Oversized nested values in outputs, logs, streamed fields, or async status payloads may be replaced with a versioned reference:

{
  "__simLargeValueRef": true,
  "version": 1,
  "id": "lv_abc123DEF456",
  "kind": "array",
  "size": 12582912,
  "key": "execution/workspace-id/workflow-id/c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74/large-value-lv_abc123DEF456.json",
  "executionId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
  "preview": { "length": 25000 }
}

Treat this as an opaque placeholder. version is part of the contract; id, key, and executionId are not fetch URLs. Reduce the payload or select a smaller field. A Response block remains subject to the v2 response contract and size limits.

File outputs contain metadata by default; request inline base64 only when needed. JavaScript Function code can read large files, value references, and manifest-backed arrays with sim.files and sim.values under memory caps. See Function.

Manual draft execution

V2 supports explicit run.source: "manual" for a personal API-key or OAuth caller with Write access. Workspace keys and anonymous callers cannot use it. Choose run.entry.blockId when several triggers are runnable; mock payloads and explicit input cannot be combined.

Manual mode uses the saved draft and supports sync or streaming, not async. Run-from-block and stop-after options have additional validation. See Execute workflow for the full request.

Limits and recovery

Execution time limits

See run duration for current billing-enabled defaults and self-hosted configuration. Async callers can shorten, but never extend, the account policy.

Execution retention

Completed and failed runs are read from execution logs and follow the effective data retention policy.

Capacity limits

A request rejected for rate or capacity limits can return 429 or 503. V2 uses a structured error envelope, for example:

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Server is at capacity. Please retry shortly."
  }
}

Use the HTTP status and Retry-After header for retry timing. If an async enqueue outcome is uncertain and the error includes a run ID, reconcile that run before repeating a request. X-Run-Id claims are one-shot identifiers, not cached-response replay keys; a conflict or missing run does not prove the first call had no effects.

Rate limits

Plan and deployment policy govern rate and concurrent execution limits. X-RateLimit-* headers describe the applicable request limit. Async mode remains subject to admission and execution limits; it does not bypass them.

API key management

Revoke a compromised key in Settings → Sim API keys, create a replacement, and update callers. Use separate keys for applications or environments and the appropriate personal/workspace scope. See authentication for key lifecycle and access.