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¶
| 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 GET of this URL starts a real run - 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. A HEAD request is refused
with HTTP 405 and starts nothing.
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.
Sending the key in a header¶
The same call is also accepted at a second address that keeps the API key out of the URL, in an
FR-Access-Key header. The URL then stops being a credential: on its own it starts nothing, so a link
preview, a browser prefetch or a URL pasted into a chat cannot start a run.
Use this address in code that can send headers. The address in Endpoint, with the key in the path, is deprecated: it keeps working, and no date has been set for removing it.
The GET example, sent this way:
curl --header "FR-Access-Key: {api-key}" \
"https://api.flowrunner.ai/api/v1/{workspace-id}/flows/{flow}/activate?orderId=1042"
The POST example, sent this way:
curl --request POST \
--url "https://api.flowrunner.ai/api/v1/{workspace-id}/flows/{flow}/activate" \
--header "FR-Access-Key: {api-key}" \
--header "Content-Type: application/json" \
--data '{
"orderId": 1042
}'
Everything else works as on the address in Endpoint: GET or POST, the query parameters, the body,
the response, and the error codes, plus 2029 below. What changes is where the key goes:
- The header is the only place this address reads the key. Without it, the call is refused with
2029. A system that can only be given a URL cannot send a header; give it the address in Endpoint, and share that URL only as text, never as a clickable link - see Calling with GET. Authorization: Beareris not read. A key sent that way counts as missing, and the answer is2029.- The header wins on the address in Endpoint too. Sent alongside the key in the path, a wrong
FR-Access-Keyheader is refused with2027, even when the path holds the right key.
The dialog that writes the call for you writes the address in Endpoint. To send the key in a header, use the address above and move the key into the header.
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:
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 missing or wrong API
key is refused with HTTP 401 instead, and a wrong media type or method is refused at the HTTP level
(415 / 405) with no code. This is what the endpoint returns for a name
with no LIVE flow behind it; the message echoes what you sent:
{
"code": 28053,
"details": {},
"message": "Flow with ID or name 'No Such Flow' 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 (Paused) 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 |
HTTP 401. The API key is wrong: not this workspace's key, or an empty or wrong FR-Access-Key header |
Re-copy the API Key from Workspace Settings ▸ General ▸ Credentials. Regenerating the key invalidates every URL built on the old one |
2029 |
HTTP 401. The /api/v1/ address was called without an FR-Access-Key header; the message reads Access Key is missing. Send it in the FR-Access-Key header. |
Send the API key in that header - see Sending the key in a header |
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 |
400 |
The POST body is not valid JSON; the message reads Request body is not valid JSON. and there is no details |
Check that the body parses - a trailing comma or an unquoted key is the usual cause - and send it again |
| HTTP 405 | PUT, DELETE and HEAD are refused |
Use GET or POST. A refused request starts no 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 |
28063 |
HTTP 400 with the message Exceeded the limit of N flow executions per billing period: the workspace's monthly execution allowance is used up. No new run starts until the billing cycle resets or the plan is raised (see Billing) |
28087 |
Too many runs are executing at once - 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 run of 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 a run of 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) ▸ How long the call waits).
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:
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.
Related¶
- Call Flow (Blocking) - starting a run and waiting for its answer
- Activating an External Callback - letting a specific waiting run continue
- Checking a Run's Status - asking what became of a run, by its
executionId - Retrieving Block Results - reading what an individual block of the run produced
- Workspace Settings - where the Workspace ID and API Key live
- Call Flow - the block that does the same job from inside another flow
