Running workflows
Run a template or a saved workflow from code, then follow the run to the files.
Read as MarkdownA workflow is a saved graph of steps. Each step is an ordinary generation. One call runs them all, in order, and each step's output feeds the next.
- Build workflows in the app, run them from code. No API or MCP tool creates or edits a graph.
- A template is a ready-made workflow. Run it as is, or fill its inputs.
1. List templates
curl -s https://app.riffads.com/api/v1/workflows/templates \
-H "Authorization: Bearer $RIFFADS_API_KEY"{
"ok": true,
"templates": [
{
"template_key": "ugc_face_cam",
"name": "Creator to camera",
"step_count": 7,
"inputs": [
{ "node": "f_brand", "label": "Brand context", "field": "text",
"field_label": "value", "kind": "text", "max_length": 8000, "filled": true }
]
}
]
}Each inputs entry is a value you may set. kind is text, setting, actor or voice. Node ids can't be guessed, so read them from this list.
Replace the example text
Template text inputs hold example copy about an invented product. Set them, or you get an ad for something you don't sell.
2. Start a run
curl -s -X POST https://app.riffads.com/api/v1/workflows/templates/ugc_face_cam/invoke \
-H "Authorization: Bearer $RIFFADS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"max_credits": 1500,
"inputs": [
{ "node": "f_brand", "field": "text", "value": "Lumen Skin, direct to consumer skincare." }
]
}'A saved workflow: POST /workflows/{workflow_id}/invoke, same body.
The answer is 201 with a workflow_run_id (wfr_). Nothing is finished yet.
| Body field | Rule |
|---|---|
max_credits | Required. Spend cap for the whole run, every step |
inputs | Optional. Up to 60 { node, field, value } |
value | String, number or boolean. actor takes an act_ id, voice a voc_ id |
- Inputs change this run only. The saved workflow stays as it is.
- One bad input refuses the whole call. Nothing starts, nothing is charged.
- You can't pass files through
inputs, and you can't setcountor a wired field. - The key needs the Workflows scope, or you get
403 insufficient_scope. - The first run of a template creates a copy in your workspace named with
(agent). Later runs reuse it.
One run at a time per workflow
Starting it again while it runs: 409 submission_in_flight. A blind retry after the first run ends starts, and charges, a second run.
3. Watch the run
There is no wait endpoint for runs. Read GET /workflow-runs/{id} (MCP: get_workflow_run, CLI: riffads workflows run <id> --wait) about every 30 seconds until run.still_running is false.
| Run status | Means |
|---|---|
queued, running | Still going |
completed | Every step finished |
partial | Some steps finished, some failed or were skipped |
failed | Nothing finished |
canceled | Stopped before any step finished |
- Files are at
run.nodes[].generations[].outputs[].url. Same 600 second signed links as a single generation. Getting results. - A failed step has
error.code:provider_error,moderation,timeout,canceled,insufficient_credits,invalid_inputorunknown. - A
skippedstep never ran because an input failed.
Stop or retry
Only in the app. There is no cancel or retry over REST, MCP or CLI. On partial or failed, read each step's error, fix the input, and start a new run.
A talking actor step makes its own voice first. No need to run the two steps yourself.