Skip to content

Call Flow (Non-Blocking)

The non-blocking Call Flow endpoint starts an instance of a FlowRunner™ flow with one GET or POST request and returns at once: the response carries the new run's executionId, and the run continues on its own. Use it when you only need the work started - a long job, a batch, a flow that pauses at an External Callback - or when the run may outlast the blocking call's 300-second maximum wait. When your code needs the flow's result in the same request, use Call Flow (Blocking) instead.

Endpoint

https://api.flowrunner.ai/{workspace-id}/{api-key}/automation/flow/{flow}/activate
Placeholder Value Where it comes from
{workspace-id} The workspace the flow belongs to Workspace Settings ▸ General ▸ Credentials - see Workspace Settings
{api-key} The workspace's API key Same place
{flow} The flow's id, or its name URL-encoded (Order%20Lookup) - either one works The id is the segment after /flow/ in the address bar while the flow is open; the name is in the breadcrumb and the flows list - see Flows. Both forms are case-sensitive. An id URL survives a rename; a name URL does not. The Launch Flow Instance dialog writes the id form

Every query parameter, and every property of a POST body, becomes one value in the run's Initial Data - this endpoint has no parameters of its own, so leave waitResponseTimeoutSeconds out (here it would land in Initial Data like any other name). The endpoint answers only while a version of the flow is LIVE; otherwise the call is refused with error 28053.

Calling with GET

Copy, fill in the placeholders, and run - the flow's values travel in the query string:

curl "https://api.flowrunner.ai/{workspace-id}/{api-key}/automation/flow/{flow}/activate?orderId=1042"

A GET needs no headers. Each query parameter becomes one value in the run's Initial Data, under its own name. Query values arrive as text: orderId=1042 reaches the flow as "1042". A query string carries text only, so call with POST when the flow needs numbers, booleans, or structured values to arrive typed. Any fetch of this URL starts a real run - a HEAD request, a chat link preview, a browser prefetch, or an uptime monitor included - and this call returns at once, so an accidental run is easy to miss. Share the URL as text, never a clickable link.

Calling with POST

The same call with the flow's values as a JSON body:

curl --request POST \
  --url "https://api.flowrunner.ai/{workspace-id}/{api-key}/automation/flow/{flow}/activate" \
  --header "Content-Type: application/json" \
  --data '{
    "orderId": 1042
  }'

A POST body is a JSON object, sent with Content-Type: application/json (a charset parameter is fine; any other media type is refused with HTTP 415). Each top-level property becomes one value in the run's Initial Data, with its JSON type kept: {"orderId": 1042} reaches the flow as the number 1042. An empty object {} is valid, and so is a POST with no body at all.

When a POST carries both a body and query parameters, FlowRunner merges the query parameters into the body object. Two rules follow from that, and both are refusals rather than silent surprises: a key sent both ways is refused with 28064, and a body that is valid JSON but not an object - an array, a bare string - is refused with 28064 too, because there is no object to merge into. A non-object body on its own, with no query parameters, is still accepted: the run starts with nothing for Initial Data to pick up by name.

Response

The call returns HTTP 200 as soon as the run exists. The body carries the run's identity and nothing else, because the run has not finished:

{
  "executionId": "4CE29875-0BD4-4AE4-B75C-60FCC55F4436"
}

The id finds the run on the flow's Instances tab (see Running Flows), and names the run when you continue it at an External Callback. It is also how your code asks what became of the run: hand it to Checking a Run's Status to learn whether the run is still going and how it ended, or to Retrieving Block Results to read what an individual block produced. Neither returns the flow's own answer - a Return Result block has no result alias - so when you need that value, either use Call Flow (Blocking) and let it wait, or have the flow deliver the answer itself: an HTTP Request from the flow to your endpoint, carrying the result and the run's Execution ID. Every step can read that id under Flow Context - Waiting on an External System shows how. Match it to the executionId this call gave you.

Errors

Most refusals come back as HTTP 400 with a JSON code, message, and details; a wrong media type or method is refused at the HTTP level (415 / 405) with no code. This is what the endpoint returns when it is given the flow's name, because it expects the id:

{
  "code": 28053,
  "details": {},
  "message": "Flow with ID 'Order Lookup' and status 'LIVE' is not found."
}
Code What it means What to do
28053 No LIVE flow with that id or name Check the identifier is cased exactly as FlowRunner shows it - a name also has to be URL-encoded (Order%20Lookup), and a + is not read as a space - and that a version is LIVE. A paused version (On hold) answers this too, so put it back with Resume flow in the flow's toolbar (see Running Flows). Renaming the flow breaks a name URL but leaves an id URL working
2027 The API key is not this workspace's key Re-copy the API Key from Workspace Settings ▸ General ▸ Credentials. Regenerating the key invalidates every URL built on the old one
9000 No workspace with that id Re-copy the Workspace ID from Workspace Settings ▸ General ▸ Credentials
28064 Query parameters could not be merged into the body: either the same key was sent both ways, or the body is valid JSON but not an object Read the message - it names the duplicated key, or says the body is not an object. Send each value once, and make the body an object whenever you also send query parameters
28045 The flow can be called only by its schedule Turn off Allow only scheduled flow instances in the version's Flow Execution Policy - see Flow Scheduling
HTTP 415 A POST body sent without Content-Type: application/json Send that header
HTTP 405 PUT and DELETE are refused Use GET or POST. HEAD is not refused - it is answered like GET and starts a run

Rate and plan limits

Code What it means
999 / 997 / 995 A request-rate limit was exceeded - back off
998 Too many requests are in flight at once - back off
28083 The workspace's monthly execution allowance is exhausted - wait for the month to reset, or raise the plan (see Billing)
28087 / 28132 Too many runs are executing at once / the execution maximum is reached - retry once some finish
28086 The maximum number of active flows has been exceeded - stop a LIVE flow you no longer need, or raise the plan

Starting a flow that waits for a callback

A flow that contains an External Callback trigger does not run start to finish. The run stops at that block and waits for an outside call before it continues. This endpoint is the right way to start such a flow: a blocking call would sit waiting at the trigger until its timeout ran out, leaving you no id for the waiting run (see Call Flow (Blocking) ▸ Timeout).

Keep the executionId this call returns. Several runs can wait at the same block, and the block's URL names the flow and the block, not the run - so when the outside system calls back, the executionId is what tells FlowRunner which run to continue. See Activating an External Callback for that call, including the cases where you do not need the id.

Let FlowRunner write the call for you

For a flow with no Return Result block, the Launch Flow Instance dialog writes this page's URL, with the flow's id and your credentials already filled in, on its GET URL and cURL tabs. Open it with Run Instance in the toolbar at the top of the flow - the dialog is pictured in full on Call Flow (Blocking). Here it is for Order Poller, which reads nothing from Initial Data, so no form is shown:

The Launch Flow Instance dialog for a flow without a Return Result block (Order Poller): a Previous Instance selector, no Initial Data form, and the GET URL tab explaining that the flow has no Return Result block so a non-blocking request URL is provided; the box labelled "GET URL - Non-blocking request" holds the URL ending in the flow's id followed by /activate.

For a flow that has a Return Result, the dialog writes the blocking URL instead - to start such a flow without waiting, build this page's URL yourself from the Endpoint template, with the id from the flow's address bar.