Triggering a flow
Call the endpoint an API Trigger node creates, with your values and asset ids.
A flow becomes callable from the API when it contains an API Trigger node. The node's sub-items (Market, Language, Version, Text, Value, Colour, Dropdown, Tags, Image, Video, Audio) are the inputs your call supplies; everything else about the flow, its templates, outputs and delivery, stays configured in Nubu.
Reading the trigger
GET /flows lists the organisation's flows with an api_trigger flag. GET /flows/<id> describes the trigger:
{
"flow": {
"id": "...",
"name": "Summer sale",
"api_trigger": {
"node_id": "...",
"auto_queue": false,
"fields": [
{ "key": "market", "label": "Market", "kind": "market", "required": true, "multiple": false },
{ "key": "hero_image", "label": "Hero image", "kind": "image", "required": true, "multiple": false }
],
"trigger_url": "https://app.nubu.app/api/v1/flows/<id>/trigger",
"example_call": { "method": "POST", "url": "...", "headers": { ... }, "body": { ... }, "curl": "..." }
}
}
}
The same example call is shown under the node in the flow editor, ready to copy.
Calling it
curl -X POST https://app.nubu.app/api/v1/flows/<id>/trigger \
-H "Authorization: Bearer nubu_api_..." \
-H "Content-Type: application/json" \
-d '{
"market": "United Kingdom",
"headline": "Summer Sale",
"hero_image": "<asset id>",
"product_video": "<asset id>",
"auto_queue": false,
"external_id": "customer-job-48291",
"callback_url": "https://your-app.example/nubu/callback"
}'
The body is flat: one key per input, using the key the description shows.
- Market, Language, Version, Text, Value, Colour and Dropdown inputs take one value each (a string; a Dropdown must be one of its
options). - Tags take an array of strings, or one comma-separated string.
- Image, Video and Audio inputs take an asset id from the library (Uploading assets). An input marked
"multiple": true(one wired to an Image, Video or Audio node) takes an array of asset ids. The asset must belong to the organisation, be fully uploaded and be of the input's kind. auto_queue(optional,trueorfalse) decides where the build lands:truesends the creatives straight to the render queue, absent orfalseleaves them in review for approval. The call decides; the API Trigger node's Auto Queue toggle only sets this key's value in the example call.external_id(optional, up to 200 characters) is your own reference; it is echoed on the run and in every callback.callback_url(optional, an https address) receives a POST every time the run changes state (Callbacks).
Nubu checks that the key belongs to the flow's organisation and has flows.run, that the flow and its campaign are not archived, that every required input is present, that values are of the right shape, that dropdown values are among the options, and that the asset ids exist, belong to the organisation and match their input's kind. Anything wrong answers 422 validation_failed with one details entry per problem (field, code, message); nothing is built.
Idempotency
Send an Idempotency-Key header (1 to 255 characters of your choosing, unique per job) and a retry can never build twice:
curl -X POST https://app.nubu.app/api/v1/flows/<id>/trigger \\
-H "Authorization: Bearer nubu_api_..." \\
-H "Idempotency-Key: order-48291-v1" \\
-H "Content-Type: application/json" \\
-d '{ "market": "United Kingdom", "external_id": "customer-job-48291" }'
- The first call with a key runs the flow and records the key on the run.
- A repeat with the same key and the same body inside 24 hours answers
200with the ORIGINAL run (run_id, its currentstatus,adopted) and"idempotent_replay": true; nothing runs again, no new run is recorded, no callback is sent. - The same key with a different body answers
409 conflictwithdetails.reasonidempotency_conflict. - After 24 hours the key is free to use again; a call then runs afresh.
Without the header every call is its own run (a repeat call with the same input still never renders twice: Runs and creatives, "Calling a trigger again").
The answer
{ "success": true, "run_id": "...", "status": "review", "external_id": "customer-job-48291", "auto_queue": false, "adopted": { "count": 0, "creative_ids": [] } }
The answer is 202: the build has run and the creatives exist. Their next step depends on the call's auto_queue key: true, the creatives go straight to the render queue ("status": "queued"); absent or false, they wait for approval ("status": "review"), which a producer gives in Nubu or your software gives through the API (Runs and creatives). The answer echoes auto_queue so you can see which destination applied.
When the call asked for auto_queue: true but the organisation's storage is full (or the member the key acts as cannot queue renders), the build still succeeds and the creatives wait in review: the answer carries "queue_fallback": "storage" (or "permission") and a notice saying why, and the run keeps that notice for GET /runs/<id>, the list and every callback. Approve the creatives once space is free.
Calling the same trigger again with the same input is safe. Creatives of an earlier call that are already queued, rendering or rendered are never built or rendered again: the new run adopts them as its result (adopted carries their count and ids) and completes once they are rendered. Creatives still in review are rebuilt, and the earlier run follows the rebuilt rows. See Runs and creatives.
If the flow could not be built (a missing template, for example) the answer is still 202 with "success": false, "status": "failed" and an error naming the reason; the run is recorded so you can read it later.
A flow without an API Trigger answers 409 conflict with details.reason no_trigger; an archived flow or campaign answers 409 with flow_unavailable. Triggers count against the organisation's cap of 60 per minute.