API quickstart
Create an API key, create a workflow through the API, start a run and read its result, in one short walkthrough with working requests.
This walkthrough creates a small workflow through the API, makes it live, runs it with your own input and reads the result. The workflow takes a list of invoice lines and reshapes each one into the fields a later step would need.
Before you start
- An API key with
workflows:write,workflows:executeandruns:read(orworkflows:read). A key created under Settings > API keys in Studio has all three. See Authentication and API keys. curl, or any HTTP client.
Set the key once in your shell:
export LOOPFOUR_API_KEY="wfk_live_..."Create the workflow
Send the workflow definition to POST /workflows. It has an API trigger and one Transform step.
curl -X POST https://workflow.loopfour.ai/api/v1/workflows \
-H "x-api-key: $LOOPFOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Reshape invoice lines",
"description": "Maps raw invoice lines to number, amount and customer",
"trigger": { "type": "api" },
"inputSchema": {
"type": "object",
"required": ["lines"],
"properties": { "lines": { "type": "array" } }
},
"steps": [
{
"id": "map_lines",
"type": "transform",
"name": "Map invoice lines",
"config": {
"operation": "map",
"data": "{{input.lines}}",
"mapping": {
"invoiceNumber": "number",
"amount": "total",
"customer": "customer.name"
}
}
}
]
}'The API answers 201 (abridged below). Keep data.id: it is the workflow id, used as $WORKFLOW_ID in the next steps. A new workflow is a draft at version label v0.1.
{
"success": true,
"data": {
"id": "8d0c4a52-0000-4000-8000-000000000001",
"name": "Reshape invoice lines",
"status": "draft",
"version": 1,
"versionLabel": "v0.1",
"trigger": { "type": "api" },
"steps": [ ... ]
}
}Activate it
A run can start only when the workflow is active. Activation is the same action as Deploy in Studio.
curl -X POST https://workflow.loopfour.ai/api/v1/workflows/$WORKFLOW_ID/activate \
-H "x-api-key: $LOOPFOUR_API_KEY"{
"success": true,
"data": { "id": "8d0c4a52-...", "status": "active", "version": 2, "versionLabel": "v1.0" }
}Activation checks the steps first. A definition with a broken step is refused with 400 and the reason.
Start a run
Post the run input to POST /workflows/:id/run. Everything under input is available to steps as {{input.<path>}}.
curl -X POST https://workflow.loopfour.ai/api/v1/workflows/$WORKFLOW_ID/run \
-H "x-api-key: $LOOPFOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"lines": [
{ "number": "INV-1001", "total": 1200, "customer": { "name": "Acme Ltd" } },
{ "number": "INV-1002", "total": 450, "customer": { "name": "Birch & Co" } }
]
},
"idempotencyKey": "reshape-2026-11-12"
}'The API answers 202 straight away, and the run continues in the background. Keep data.run_id as $RUN_ID.
{
"success": true,
"data": {
"run_id": "c51e7f10-0000-4000-8000-000000000002",
"status": "pending",
"workflow_id": "8d0c4a52-...",
"mode": "async"
}
}Sending the same idempotencyKey again for this workflow returns the existing run (200) instead of starting a second one.
Read the run
curl https://workflow.loopfour.ai/api/v1/runs/$RUN_ID \
-H "x-api-key: $LOOPFOUR_API_KEY"When status is completed, output holds the output of the last step, and stepResults holds one entry per step (abridged here):
{
"success": true,
"data": {
"id": "c51e7f10-...",
"workflowId": "8d0c4a52-...",
"status": "completed",
"triggerType": "api",
"output": [
{ "invoiceNumber": "INV-1001", "amount": 1200, "customer": "Acme Ltd" },
{ "invoiceNumber": "INV-1002", "amount": 450, "customer": "Birch & Co" }
],
"stepResults": [
{ "stepId": "map_lines", "status": "success", "durationMs": 12, "attempt": 1 }
],
"startedAt": "2026-11-12T10:00:00.000Z",
"completedAt": "2026-11-12T10:00:01.000Z",
"error": null
}
}Poll until status is completed, failed or cancelled. A run with an Approval step waits in waiting_approval until someone decides.
Wait for the result in one call
For short workflows you can ask the run endpoint to wait. Add "mode": "sync" and, optionally, maxExecutionTimeMs (1,000 to 300,000; default 30,000).
curl -X POST https://workflow.loopfour.ai/api/v1/workflows/$WORKFLOW_ID/run \
-H "x-api-key: $LOOPFOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": { "lines": [] }, "mode": "sync", "maxExecutionTimeMs": 60000 }'A finished run returns 200 with output and duration_ms. If the wait runs out first, you get 202 with timed_out: true and the run_id to poll, unless you set "onTimeout": "throw_error", which returns 408 with code SYNC_TIMEOUT.
What to try next
- Add a step that reads
{{steps.map_lines}}. See Variable references. - Replace the API trigger with a schedule or an inbound email address. See Triggers.
- Look up the blocks and integration actions you can use with
GET /blocks. See Block and action discovery.
Developers
Use the Loopfour API, webhooks and MCP to create and run workflows from your own systems, with reference pages for each block and integration.
Authentication and API keys
Authenticate API requests with the x-api-key header, choose the scopes a key needs, and create or revoke keys under Settings and API keys.
Loopfour