Skip to main content
Running a flow is asynchronous: you start a run and get a runId back immediately, then poll until it completes. This guide walks through the whole thing. All examples assume you’ve set FLOWY_API and FLOWY_KEY from Authentication.
This touches all three scopes: listing and fetching a flow needs apps:read, starting the run needs runs:write, and polling needs runs:read. A Full-access key has all three; a Read-only key can do every step except start the run.
1

Find the flow you want to run

List the flows in your workspace and grab a flow’s id.
Response
2

Look up the flow's inputs

Fetch the flow to see which inputs it expects. Each input’s name (its kebab-cased title) is the node_id you’ll send in the run request.
Response
Use each input’s name (here selfie, style, references) as the node_id in the run request below.An input carrying arity is a variable input: the run accepts between arity.min and arity.max values for that one key. Send them as an array-valued asset_url (or prompt for text). Values beyond arity.max are ignored.
Advanced options. params lists the generation settings the flow’s author chose to expose (resolution, duration, voice, …), separate from inputs, and always optional. Each has a default (the node’s published value at the time the flow was published) and, for enum/number kinds, the allowed enumValues / min / max / step; group names the node it belongs to. Send a param’s name as a key in the run request’s params object (next step). Omit any you don’t want to override. The run uses its published default.
3

Start the run

POST to the flow’s runs endpoint with an inputs array, unchanged from before, plus an optional params object for anything from the previous step’s params list. Each inputs entry’s node_id is a content input’s name; set its value with asset_url for media inputs (a URL) or prompt for text inputs (the text itself), an array for a variable input (arity). Each params entry is keyed by the param’s name, with a value matching its kind (a string for enum/text, a number, or a boolean). You get a runId back right away.
Response
inputs stays lenient: an unrecognized node_id or a missing required content input never fails the request. Each is reported back as a warnings entry instead (unknown_input / missing_input), and the run still starts:
Response with warnings
params is the opposite: it’s new, so it’s strict. An unknown name or an out-of-range/wrong-type value is rejected with 400 before the run starts. See Errors for unknown_param and invalid_param.
4

Poll until it's done

Poll the run every couple of seconds until status is completed or failed. There’s no separate outputs array. A run’s result surface is nodeResults, its per-node record; the entries with isOutput: true are the ones the flow publishes (each carrying name, kind, and url or text). Output media URLs are signed and ready to download.
Response
A node absent from nodeResults was never executed (downstream of a failure, or a pass-through constant). A failed run’s non-output entries, status: "failed" with an error, are there for debugging, not part of the published result.
Output URLs are signed and expire. Download or copy the asset to your own storage soon after the run completes rather than storing the URL long-term.
Last modified on September 8, 2026