Loopfour
Triggers

API trigger

Start a workflow run with an API call, pass input in the request body, and read the run that the call creates through the Runs API.

The API trigger starts a run when your system calls POST /workflows/:id/run. Use it when your own application decides when the work should happen, for example after a month-end batch is ready.

Configuration

{ "trigger": { "type": "api" } }

There are no other fields. In Studio, the API block in the Triggers group shows the run endpoint for the workflow. The request body's input reaches steps as {{input.<path>}}.

Start a run

POST /workflows/:id/run needs the workflows:execute scope and counts against the execute rate limit (500 requests per minute per key). The workflow must be active.

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": {
      "customerId": "CUST-0042",
      "period": "2026-10",
      "amount": 12500
    },
    "idempotencyKey": "invoice-CUST-0042-2026-10"
  }'

Request body

FieldTypeDefaultMeaning
inputobject{}The run input. Checked against the workflow's inputSchema when one is set
idempotencyKeystringnoneA key for this request. A second call with the same key for the same workflow returns the existing run instead of starting a new one
modeasync or syncasyncsync waits for the run to finish before answering
maxExecutionTimeMsnumber, 1,000 to 300,00030,000How long a sync call waits
onTimeoutreturn_run_id or throw_errorreturn_run_idWhat a sync call does when the wait runs out
onFailurethrow_error or switch_to_asyncthrow_errorWhat the call returns when the run fails or cannot be queued

Responses

SituationStatusdata
async run queued202run_id, status: "pending", workflow_id, mode: "async"
Same idempotencyKey seen before200run_id and status of the existing run, workflow_id, message
sync run finished200run_id, status, workflow_id, mode: "sync", output, duration_ms
sync wait ran out (return_run_id)202run_id, status, mode: "async", timed_out: true
Run failed, onFailure: "switch_to_async"202run_id, status: "failed", error, switched_to_async: true

The response fields of this endpoint use snake case (run_id, workflow_id). The Runs API uses camel case.

Errors

StatusCodeCause
400WORKFLOW_NOT_ACTIVEThe workflow is a draft, paused or archived
400VALIDATION_ERRORinput failed the workflow's inputSchema; details.errors lists each problem, such as Missing required field: customerId
404NOT_FOUNDNo workflow with that id in your company
408SYNC_TIMEOUTA sync wait ran out and onTimeout was throw_error
500TRIGGER_ERRORThe run was recorded but could not be queued. It is marked failed
500the run's error code, or WORKFLOW_FAILEDA sync run failed and onFailure was throw_error. details.run_id names the run

The input check covers the required list and the top-level type of each property. It does not look inside nested objects.

Follow the run

curl https://workflow.loopfour.ai/api/v1/runs/$RUN_ID \
  -H "x-api-key: $LOOPFOUR_API_KEY"

The response has status, input, output, stepResults, error, startedAt, completedAt and durationMs. Poll until status is completed, failed or cancelled; a few seconds between calls is enough for most workflows. GET /runs/:id/logs returns the step-by-step log. See the Runs API.

Run any workflow on demand

This endpoint starts any active workflow, whatever its trigger type. That makes it the simplest way to test a webhook, email or schedule workflow: post an input in the shape that trigger would produce. For a webhook workflow:

{
  "input": {
    "webhookEvent": {
      "provider": "stripe",
      "eventType": "invoice.paid",
      "payload": { "data": { "object": { "id": "in_123", "amount_paid": 9900 } } }
    }
  }
}

Studio's Run button calls the same endpoint. Those runs are recorded with trigger type manual instead of api.

On this page