Runs

Start a workflow run with inputs, follow it to what it hands back, list past runs, stop a run in progress, and delete one.

A run is one pass through a workflow. Runs start in the background: you start one, get its ID straight away, and check it until it finishes. The API calls a run an execution, so its ID is execution_id and its endpoints are under /executions.

The run object

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "workflow_id": "665f1a2b3c4d5e6f7a8b9c0d",
  "version_id": "6683e1c4b2a9d7f0e5c3a1b2",
  "workflow_name": "Monthly Client Report",
  "status": "success",
  "is_trigger_listener": false,
  "created_at": "2026-01-15T10:30:00+00:00",
  "started_at": "2026-01-15T10:30:00+00:00",
  "completed_at": "2026-01-15T10:30:03+00:00",
  "error": null,
  "outputs": { "total": 1250, "summary": "A good month for Acme" }
}

Fields

execution_idstring
The run's ID.
workflow_idstring
The ID of the workflow that ran. It stays the same when the workflow is edited.
version_idstring
The ID of the version of the workflow that ran. It changes as the workflow is edited.
workflow_namestring
The workflow's name.
statusstring
Where the run is, such as running or success. See Run statuses.
is_trigger_listenerboolean
Whether this run is a workflow that starts from its own trigger or schedule, listening. See Workflows that start themselves.
created_atstring
When the run was started, in ISO 8601.
started_atstring or null
When it began working, in ISO 8601, or null while it's queued.
completed_atstring or null
When it finished, in ISO 8601, or null while it's still going.
errorstring or null
Why the run failed, or null.
outputsobject
What the run handed back: one field per output its workflow declares, by name. Empty until the run succeeds, and for a workflow that declares none. An output the run never set is null. Only Get a run includes it.

Run statuses

StatusMeaningFinal?
queuedStarted, and about to beginNo
runningWorking through its stepsNo
waitingSet aside by a Wait step until its time comesNo
awaiting_approvalWaiting for someone to answer an approval requestNo
successReached the end of the workflowYes
failedA step failed and the run stopped thereYes
stoppedStopped before it finishedYes

When you check a run until it's done, wait for one of the final statuses rather than for it to leave running: a run waiting on a Wait step or an approval isn't finished.

Workflows that start themselves

A workflow that starts from its own trigger or schedule doesn't run to an end. Running it turns it on, and the run you get back is the workflow listening: is_trigger_listener is set, and its status reads running for as long as it listens. Each event or scheduled time it catches starts a run of its own, which List runs lists beside it. Don't wait for the listening run to finish; follow the runs it starts instead, and stop it to turn the workflow off.


Run a workflow

POST/api/v1/workflows/:id/run-async

Starts a run in the background and returns its ID straight away; follow it with Get a run. Requires the workflows:execute scope, and the member who created the key must be allowed to run workflows (the Run workflows role permission).

:id can be the workflow's id or the ID of any of its versions. Either way, the workflow runs as it is now. Each run counts as one of your plan's monthly runs; when they're used up, the request gets 429 with the code monthly_run_limit (see Error codes).

Headers

Idempotency-Keystring
Makes the request safe to retry: a repeat with the same key returns the first response instead of starting another run. Up to 256 characters, remembered for 24 hours. Reusing a key for a different request, such as the same workflow with different inputs, returns 422. See Idempotency.

Body

Optional. To give values for the inputs the workflow declares, send a JSON object of at most 500 KB whose only field is inputs.

inputsobject
Values for the workflow's inputs, by input name.
{
  "inputs": {
    "client": "Acme",
    "month": "2026-05"
  }
}

How inputs are checked

Each value is converted to its input's declared type:

TypeAccepts
textAny value, as text
numberA number, or text that reads as one, such as "21"
booleantrue or false, or text such as "yes", "no", "on" or "0"
listA list, or comma-separated text
objectAn object

An optional input you leave out takes its default, so a workflow with no required inputs can be run without a body. The run is refused with 400 and the code invalid_inputs, before anything starts and with a message naming the input, when:

  • a value names an input the workflow doesn't declare
  • a required input has no value
  • a value can't be converted to its input's type
  • a value can't be stored with a run, such as NaN, Infinity, a whole number wider than 64 bits, or lists and objects nested more than 32 levels deep

A workflow that starts from its own trigger or schedule takes no inputs, and sending it some returns 400. Running it without a body turns it on, so it starts listening for its trigger or schedule: the response has is_trigger_listener set. See Workflows that start themselves.

Example

curl -X POST https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d/run-async \
  -H "Authorization: Bearer $LODOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: acme-report-2026-05" \
  -d '{"inputs": {"client": "Acme", "month": "2026-05"}}'

Response 202:

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "workflow_id": "665f1a2b3c4d5e6f7a8b9c0d",
  "version_id": "6683e1c4b2a9d7f0e5c3a1b2",
  "status": "queued",
  "is_trigger_listener": false,
  "created_at": "2026-01-15T10:30:00+00:00"
}

Response 400:

{
  "error": "'Monthly Client Report' needs a value for its 'client' input.",
  "error_code": "invalid_inputs"
}

List runs

GET/api/v1/executions

Returns the workspace's runs, newest first, a page at a time. Requires the executions:read scope. The runs a workflow that starts itself starts are listed too, beside its listening run. A workflow another run called isn't listed on its own: it's part of the run that called it.

Query parameters

workflow_idstring
Only runs of this workflow, from every version of it. Takes the workflow's id or the ID of any of its versions.
limitinteger
How many runs to return, from 1 to 100.Default: 20.
afterstring
For the next page: the execution_id of the last run on the page you have.
curl "https://api-prod.lodol.com/api/v1/executions?workflow_id=665f1a2b3c4d5e6f7a8b9c0d&limit=10" \
  -H "Authorization: Bearer $LODOL_API_KEY"

Response 200: a page of run objects, each with its error but without outputs: Get a run has them.

{
  "executions": [
    {
      "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
      "workflow_id": "665f1a2b3c4d5e6f7a8b9c0d",
      "version_id": "6683e1c4b2a9d7f0e5c3a1b2",
      "workflow_name": "Monthly Client Report",
      "status": "failed",
      "is_trigger_listener": false,
      "created_at": "2026-01-15T10:30:00+00:00",
      "started_at": "2026-01-15T10:30:00+00:00",
      "completed_at": "2026-01-15T10:30:03+00:00",
      "error": "The sales sheet is empty this month."
    }
  ]
}

Get a run

GET/api/v1/executions/:id

Returns one run, with the outputs it handed back once it has succeeded. Requires the executions:read scope. Step results are left out unless you ask for them, which keeps checking a run's status quick; they're for looking into how a run reached its result, while outputs is the result.

Query parameters

include_step_resultsstring
Set to true to include what each step produced, in steps.
# Check the status
curl https://api-prod.lodol.com/api/v1/executions/683b2c3d4e5f6a7b8c9d0e1f \
  -H "Authorization: Bearer $LODOL_API_KEY"

# Get every step's result once it has finished
curl "https://api-prod.lodol.com/api/v1/executions/683b2c3d4e5f6a7b8c9d0e1f?include_step_results=true" \
  -H "Authorization: Bearer $LODOL_API_KEY"

Response 200:

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "workflow_id": "665f1a2b3c4d5e6f7a8b9c0d",
  "version_id": "6683e1c4b2a9d7f0e5c3a1b2",
  "workflow_name": "Monthly Client Report",
  "status": "running",
  "is_trigger_listener": false,
  "created_at": "2026-01-15T10:30:00+00:00",
  "started_at": "2026-01-15T10:30:00+00:00",
  "completed_at": null,
  "error": null,
  "outputs": {}
}

Response 200, with include_step_results=true:

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "workflow_id": "665f1a2b3c4d5e6f7a8b9c0d",
  "version_id": "6683e1c4b2a9d7f0e5c3a1b2",
  "workflow_name": "Monthly Client Report",
  "status": "success",
  "is_trigger_listener": false,
  "created_at": "2026-01-15T10:30:00+00:00",
  "started_at": "2026-01-15T10:30:00+00:00",
  "completed_at": "2026-01-15T10:30:03+00:00",
  "error": null,
  "outputs": { "total": 1250, "summary": "A good month for Acme" },
  "steps": [
    { "index": 0, "status": "completed", "result": "..." },
    { "index": 1, "status": "completed", "result": "..." }
  ]
}

Stop a run

POST/api/v1/executions/:id/stop

Stops a run in progress. Steps that already finished aren't undone. Requires the workflows:execute scope, and the member who created the key must be allowed to run workflows. A run that has already finished (success, failed or stopped) returns 400 with the code run_already_finished: there's nothing to stop, and Get a run says how it ended.

Headers

Idempotency-Keystring
Makes the request safe to retry, as for Run a workflow.
curl -X POST https://api-prod.lodol.com/api/v1/executions/683b2c3d4e5f6a7b8c9d0e1f/stop \
  -H "Authorization: Bearer $LODOL_API_KEY"

Response 200:

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "status": "stopped"
}

Delete a run

DELETE/api/v1/executions/:id

Deletes a finished run from the history, as deleting it in Lodol does. This can't be undone. Requires the executions:delete scope, and the member who created the key must be allowed to delete runs (the Delete runs role permission); otherwise the request gets 403.

The runs it started go with it: the runs its trigger started, and the runs of the workflows it called. A run that hasn't finished, or that started one that hasn't, returns 409 with the code run_not_finished; stop it first, or wait for it to finish. Deleting a run doesn't give back the run it counted as.

curl -X DELETE https://api-prod.lodol.com/api/v1/executions/683b2c3d4e5f6a7b8c9d0e1f \
  -H "Authorization: Bearer $LODOL_API_KEY"

Response 200:

{
  "execution_id": "683b2c3d4e5f6a7b8c9d0e1f",
  "deleted": true,
  "started_runs_deleted": 0
}

started_runs_deleted says how many of the runs it started went with it. A run that doesn't exist, or is already deleted, returns 404. Deleting takes no Idempotency-Key, so if a delete times out, check with Get a run before sending it again: it may have gone through.

On this page