Start a workflow and read its result

Start a published workflow and follow its run to a terminal status with the Developer API.

This guide starts a published workflow with the Developer API, then follows the resulting run until it reaches a terminal status.

Before you start

You need an API key with the automation manage capability and the workflow.control action grant. The reads in this guide require the automation read capability, which manage also covers. See API keys to create one, and API overview for the capability levels and action grants.

Set the origin and key once for the examples:

export API_ORIGIN="https://api.factorai.ai"
export API_KEY="<your API key>"

Steps

1. List workflows

GET /v1/workflows returns the workflows visible to the key. Each item carries the workflow and its current immutable revision.

WORKFLOWS=$(curl -sS "$API_ORIGIN/v1/workflows?limit=20" \
  -H "Authorization: Bearer $API_KEY")

WORKFLOW_ID=$(printf '%s' "$WORKFLOWS" | jq -r '.workflows[0].workflow.id')
WORKFLOW_REVISION_ID=$(
  printf '%s' "$WORKFLOWS" |
    jq -r '.workflows[0].workflow.currentRevisionId'
)

Pass the response's nextCursor as the cursor query parameter to read another page.

2. Start the workflow

POST /v1/workflows/{workflowId}/start accepts a start command. The successful response is 202 with accepted: true, status: applied, commandId, and the new workflowRunId.

RUN=$(curl -sS -X POST "$API_ORIGIN/v1/workflows/$WORKFLOW_ID/start" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"command\": {
      \"kind\": \"start\",
      \"idempotencyKey\": \"start-$RANDOM\",
      \"workflowId\": \"$WORKFLOW_ID\",
      \"workflowRevisionId\": \"$WORKFLOW_REVISION_ID\",
      \"executionMode\": \"finite\"
    }
  }")

WORKFLOW_RUN_ID=$(printf '%s' "$RUN" | jq -r '.workflowRunId')

idempotencyKey identifies the command: a retry that reuses the key replays the original command instead of starting another run, and the response's replayed field reports that replay. Use executionMode continuous instead of finite for a workflow that keeps running past its first result.

3. Read the run

GET /v1/workflow-runs/{workflowRunId} returns the durable run. workflowRun.status is one of initializing, active, paused, completed, failed, cancelled, or failed-validation.

curl -sS "$API_ORIGIN/v1/workflow-runs/$WORKFLOW_RUN_ID" \
  -H "Authorization: Bearer $API_KEY" |
  jq '{status: .workflowRun.status, failureReason: .workflowRun.failureReason}'

Repeat the read while the status is initializing, active, or paused. A completed, failed, cancelled, or failed-validation status is terminal; on failed, read workflowRun.failureReason for the cause.

4. Control the run (optional)

POST /v1/workflow-runs/{workflowRunId}/control accepts pause, resume, cancel, or finish. Every control carries the run id, a unique idempotencyKey, and a reason.

curl -sS -X POST "$API_ORIGIN/v1/workflow-runs/$WORKFLOW_RUN_ID/control" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"command\": {
      \"kind\": \"cancel\",
      \"workflowRunId\": \"$WORKFLOW_RUN_ID\",
      \"idempotencyKey\": \"cancel-$RANDOM\",
      \"reason\": \"Stopping this example run.\"
    }
  }"

The response is 202 with the same accepted, commandId, command, lockVersion, replayed, and status fields as the start response.

Errors and limits

  • 401 - the request is missing a valid API key.
  • 403 - the key lacks the automation capability or the workflow.control action grant.
  • 404 - the workflow or run does not exist for the key.

See API overview for the error contract and permission layers.

Next steps