Nubu
  • Features
  • How it works
  • Pricing
  • Integrations
  • FAQ
  • Contact
  • Docs
  • Blog
  • Log in
  • Log inSign up
    Nubu

    Creative automation for teams that ship campaigns, not busywork.

    Try for free
    Product
    FeaturesNubu MotionHow it worksPricingIntegrationsFAQ
    Company
    AboutContactDocsBlogLog in
    Legal
    Privacy policyTerms of serviceData deletion
    © 2026 Bear Studios · Nubu
    Introduction
    Templates overviewInstalling Nubu BuilderAdding template compsAdding propertiesAdding footageSetting defaultsExporting your templateUploading a template
    Flows overviewAvailable nodesAdding a nodeConnecting nodesWorking with dataTemplates and outputsUsing AI nodesBuilding a creative
    CampaignsTemplatesAssetsGlossariesRendersSettings
    Connecting Meta AdsConnecting Google AdsConnecting OpenAIConnecting Gemini AI StudioConnecting Anthropic
    AI Assistant overviewPrompt examplesAssistant settings and controls
    Nubu Motion scripts: the reference
    OverviewQuick startDifferences from After EffectsDeterminism
    JavaScript supportReferences and idsProject scriptsState and timeBudgets and errorsFormatting values
    GlobalTime conversionInterpolationVector mathsRandom and noiseColour conversionOther maths
    LayerCompPropertyKeyframePathGeometryProjectComponentConsoleComponentControlExpressionControl
    The property vocabularyAnimators propertiesAudio propertiesContent propertiesContents propertiesEffects propertiesExpression controls propertiesFills propertiesInstance controls propertiesLayer propertiesLayout propertiesMasks propertiesStrokes propertiesText style propertiesRig propertiesRigging propertiesRig controllers propertiesRigging weights propertiesRigging mesh propertiesRig items propertiesRig splines propertiesRig simulation propertiesRig properties propertiesRig drivers propertiesRig draw order propertiesTransform propertiesTrim path properties
    Error codesBudgets
    Changelog
    API overviewAuthentication and keysRate limits and errorsUploading assetsFoldersUploading templatesTriggering a flowRuns and creativesAPI Request deliveryCallbacks
    All docs
    API

    Runs and creatives

    Follow a run through review, queue and render; approve, re-render, download and delete creatives.

    A run is one call of a flow's API Trigger. It owns the creatives that call built, and its state follows them.

    Reading a run#

    GET /runs/<run_id> answers the run derived from its creatives at that moment:

    {
      "run": {
        "id": "...",
        "run_version": 17,
        "status": "rendering",
        "error": null,
        "external_id": "customer-job-48291",
        "notice": null,
        "auto_queue": false,
        "adopted": { "count": 0, "creative_ids": [] },
        "counts": { "total": 3, "review": 0, "queued": 1, "rendering": 1, "rendered": 1, "failed": 0 },
        "creatives": [
          {
            "id": "...",
            "creative_id": "summer-sale-uk-a",
            "status": "rendering",
            "progress": { "stage": "rendering", "percent": 42, "frames_done": 1320, "frames_total": 3147, "started_at": "..." },
            "error": null,
            "render": null,
            "delivery": null
          }
        ],
        "completed_at": null
      }
    }
    

    auto_queue records what the call asked for (true = the render queue, Triggering a flow); when the queue fell back to review, the answer's queue_fallback and the run's notice say why.

    run_version is the run's monotonic version: it goes up by one on every state change Nubu records, and every callback carries the version it reports (Callbacks). Compare versions, never timestamps, to know which reading is newer; the list carries it too.

    The run's states#

    StatusMeaning
    processingThe flow is building its creatives, or a finished render is still being delivered by an API Request node.
    reviewCreatives are waiting for approval.
    queuedCreatives are waiting for a render machine.
    renderingAt least one creative is rendering.
    completedEvery creative has finished and at least one rendered; deliveries included.
    failedThe flow could not be built, or every creative failed.

    A run with a failed build, or one where every creative failed, carries a run-level error with a class and a message. A run that completed with some failures carries the failures on the creatives themselves, so a partial failure is always visible per creative.

    Each creative#

    • status: the creative's own lifecycle (building, review, queued, processing, rendering, rendered, failed, cancelled).
    • progress: while a render is in flight, the render machine's progress (the stage, the percentage, the frames so far, when it started).
    • error: null, or { "class", "message" }. The classes distinguish where things went wrong: asset_upload_failed, flow_processing_failed, creative_build_failed, render_failed, delivery_failed.
    • render: the finished output (its id, content type, size, dimensions, duration, when it rendered).
    • delivery: the API Request node's delivery state when the flow has one (pending, uploading, uploaded, failed, with the attempts, the HTTP status and how the render was sent). See API Request delivery.
    • adopted: true when the creative was built by an earlier call and this run reports it as its result (below).

    GET /runs lists runs, newest first, with flow_id, campaign_id, external_id and status filters; each row carries adopted_count.

    Calling a trigger again#

    A trigger call is safe to repeat: a retry, or the same job sent twice, never renders anything twice.

    • Creatives of an earlier call that are queued, rendering or rendered are left exactly as they are. The new run adopts them: they appear in its creatives with "adopted": true and their current state, the run's adopted field carries their count and ids, and the run's state follows them (it completes once they are rendered, and its callbacks report them). creatives[].id is the same id the earlier run reported, so your records line up; the earlier run keeps them too.
    • Creatives of an earlier call that are still in review are rebuilt: the new call's rows replace them (the same creative_id names, fresh ids) and the earlier run follows the rebuilt rows as its adopted creatives, so both runs report the same creatives.
    • A later call with a different input that leaves an earlier run with no creatives at all records that run as failed with the class creative_build_failed, saying which call replaced its creatives.

    The trigger's 202 answer carries the same adopted field, so a retry that adopted everything can be recognised at once.

    Working with creatives#

    • GET /creatives lists creatives (campaign_id, flow_id, run_id and status filters); GET /creatives/<id> adds the progress, the number of render attempts and, once rendered, a 15-minute download_url.
    • POST /creatives/<id>/approve sends a creative in review to the render queue, exactly as Approve does in the app. Only creatives in review can be approved; an organisation whose storage is full answers 409 conflict with details.reason storage_full until space is freed.
    • POST /creatives/<id>/rerender sends a rendered, failed or cancelled creative back to the queue. The previous render stays until the new one lands. While storage is full it answers 409 conflict with details.reason storage_full, like approve.
    • PATCH /creatives/<id> edits the copy columns (headline, primary_text, description, cta, final_url, the utm_* fields, notes), market, language, version, filename and fields. A creative that is queued or rendering belongs to the render machine and answers 409 conflict.
    • GET /creatives/<id>/download answers a 15-minute URL for the finished render, with its filename, content type and size. A creative without a finished render answers 409.
    • DELETE /creatives/<id> removes the creative and its rendered files; one mid-render answers 409.
    • POST /creatives creates a creative row outside a flow (creative_id required; the same columns as the edit).

    The renders themselves always stay stored in Nubu.