roasOS
Workflows

Remix an ad

Analyze one ad, storyboard the same structure with your product and your person, and render it.

This endpoint selects Rebuild ad: roasOS reads the reference, writes a new script in your brand voice, casts your product and your person, and proposes a storyboard before rendering new footage.

For Preserve video, use a video-edit endpoint or Recast a video. The typed remix endpoint has no mode field and keeps its Rebuild behavior even when the source is your own clip. The roasos:remix-ad skill and browser Remix page also offer Preserve video.

POST /v1/workflows/remix is the typed door onto the roasos:remix-ad skill. It starts an agent run; it is not a direct video-edit call.

A remix is an agent run, not a job

Recast and animate-a-still answer with a job. Analyze answers with an analysis. A remix answers with an agent run, because the work is a plan: it analyzes, it storyboards, it prices the board, and then it renders the approved board.

StepWhere you read it
The run itselfGET /v1/agent-runs/{id}
The light pollGET /v1/agent-runs/{id}/status
The lifecycleGET /v1/agent-runs/{id}/events
The answer of the agentGET /v1/agent-runs/{id}/result
Each render the run startedGET /v1/jobs/{id}

The caps, the quote, the reservation and the refund are those of an agent run. Refer to Agent and to Runs.

Review the storyboard before rendering

The storyboard keeps the current scene, cast, product, script and timing. Its preflight checks report problems in that board. The source ad's CTA or hook is reference evidence; it does not prove that the rebuilt ad has the same qualities. A preflight score does not predict ad performance.

Check the dialogue, product appearance and duration before approving. If the model needs a longer supported duration, the plan shows the change and its cost. A prompt that cannot fit the approved content stops for an edit; roasOS does not cut a spoken line to fit it. On-screen text is a postproduction instruction. Review the finished video for identity, product fidelity, speech, continuity and readability without sound.

In the app, Open storyboard opens that board in a visual workspace. Select a shot in the timeline to edit its direction and script. Cast, voice and outputs have separate views; render settings and review notes expand when needed. You can expand the workspace or keep a compact overview beside chat.

Previews use completed media linked to that exact shot and saved version. Reference frames and the source clip are labeled as references; a shot without matching media remains unrendered. Grouped clips and older outputs stay in Outputs. Editing a shot does not generate a new preview.

Unsaved edits survive closing, resizing, switching boards and background refreshes. If the agent saves a newer version, review it before keeping your edits on that version. Save your edits, then choose Review price for a quote-only approval card in chat. Generation starts only after approval.

Each rendering stage has a saved input and a maximum credit cost. The worker quote must fit that limit before the stage starts. Regenerating a frame is a separate purchase; its button shows the maximum cost. An older approval without a saved stage budget needs a fresh approval before starting a new stage.

After an uncertain response, retry the same approval. A request already accepted uses its stored quote and payment key, including after quote expiry. An expired quote that was never submitted needs a fresh approval. A network error alone does not prove that a request was uncharged.

1. Choose the source

Send exactly one source. Two sources, or none, answer 400 validation_error.

FieldUse it for
discover_item_idA creative from the roasOS Discover library — read the ids with GET /v1/discover/items
ad_urlA public HTTPS ad URL for analysis, or an owned source URL; send Discover ads by discover_item_id
source_generation_idThe id of a completed job in your workspace

A Discover creative is a competitor's ad. Read it, and re-create it. Never edit it.

Send a Discover ad as discover_item_id. That is the analyze path, and it is permitted. A Discover URL in ad_url, or a generation that came from one in source_generation_id, answers 400 discover_source_not_allowed. Inside the run, Discover footage is never directly edited or used as an identity/product reference. Only the storyboard compiler may carry an analyzed clip as a permitted regeneration reference; still remix may use the analyzed still for composition. Refer to Rights.

Rebuild requires a successful source analysis before writing the script or drafting a storyboard. If analysis fails, the run explains the blocker and stops. It only switches to a fresh concept when you explicitly change the brief. For an oversized video, provide a smaller export of the full source (36 MiB maximum).

2. Say what the remix must sell

FieldRule
product_idRequired. The product the remix sells. A remix without a product is a plain recast.
avatar_idOptional. The person the remix casts.
variantsOptional. 1 or 2. The default is 1. Two variants request the faithful recreation plus one alternate hook; the storyboard approval flow first requires an approved single.
noteOptional. 400 characters or fewer. roasOS reads a note as evidence, never as an instruction.

The product images and the avatar come from your workspace. Refer to Product kits and to Identity.

Make an avatar over the API with POST /v1/avatar/nano-banana-pro. The MCP tool is roasos_avatar_nano_banana_pro. Send the new id in avatar_id, or send a roasOS gallery avatar. The legacy path POST /v1/avatars answers 503 avatar_generation_unavailable.

3. Quote

Set quote_only to true. A quote is free, and it reserves nothing.

Send an Idempotency-Key header. Use 16 to 255 characters. Use the same key for the quote and for its confirm.

curl -X POST https://api.roasos.com/v1/workflows/remix \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: remix-glow-serum-001" \
  -H "Content-Type: application/json" \
  -d '{
    "discover_item_id": "6f3a9c21-4b0e-4c3a-9f52-1d7a8c0e5b44",
    "product_id": "5e6b3311-7a2c-4f19-b3d8-0c41e7f92a63",
    "avatar_id": "9c17ab42-0b53-4d1e-8f7a-2c9b6e40a115",
    "variants": 2,
    "max_credits": 25,
    "quote_only": true
  }'

The answer is 200. The status is quoted.

{
  "data": {
    "schema_version": "agent-run@1",
    "kind": "agent_run",
    "id": "6f31c07d-...",
    "trigger": "workflow",
    "skill_id": "855acde9-c801-4076-97cd-b08de3985705",
    "conversation_id": null,
    "status": "quoted",
    "max_credits": 25,
    "generation_spend_cap_credits": 0,
    "credits_reserved": 0,
    "credits_max": 25,
    "pricing_version": "agent-token-pricing@2026-10-04.v3",
    "quote_id": "b0f4e2c9-...",
    "expires_at": "2026-08-21T11:18:02.000Z",
    "authorization": { "status": "auto_approved" },
    "created_at": "2026-08-21T11:08:02.000Z",
    "updated_at": "2026-08-21T11:08:02.000Z"
  }
}

credits_max is the ceiling of the run: max_credits plus generation_spend_cap_credits. It is not an estimate.

skill_id names the pack skill the remix runs. Refer to The roasOS skill pack.

Confirm the quote inside 10 minutes. A quote that is too old answers 410 quote_expired.

4. Confirm

Send the same body with the quote_id. Use the same idempotency key. Remove quote_only.

curl -X POST https://api.roasos.com/v1/workflows/remix \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: remix-glow-serum-001" \
  -H "Content-Type: application/json" \
  -d '{
    "discover_item_id": "6f3a9c21-4b0e-4c3a-9f52-1d7a8c0e5b44",
    "product_id": "5e6b3311-7a2c-4f19-b3d8-0c41e7f92a63",
    "avatar_id": "9c17ab42-0b53-4d1e-8f7a-2c9b6e40a115",
    "variants": 2,
    "max_credits": 25,
    "quote_id": "b0f4e2c9-..."
  }'

The answer is 202. roasOS reserves the ceiling and starts the run.

{
  "data": {
    "schema_version": "agent-run@1",
    "kind": "agent_run",
    "id": "6f31c07d-...",
    "trigger": "workflow",
    "skill_id": "855acde9-c801-4076-97cd-b08de3985705",
    "conversation_id": null,
    "status": "processing",
    "max_credits": 25,
    "generation_spend_cap_credits": 0,
    "credits_reserved": 25,
    "pricing_version": "agent-token-pricing@2026-10-04.v3",
    "started_at": "2026-08-21T11:08:44.000Z",
    "pending_approvals": [],
    "created_at": "2026-08-21T11:08:02.000Z",
    "updated_at": "2026-08-21T11:08:44.000Z"
  }
}

The id is the run id. Keep it. Every later read uses it.

5. Poll the run

curl https://api.roasos.com/v1/agent-runs/6f31c07d-.../status \
  -H "Authorization: Bearer roasos_sk_..."

An agent run sends no webhook. Poll every few seconds.

The events show what the run did.

{
  "data": [
    { "seq": 0, "event": "accepted", "at": "2026-08-21T11:08:02.000Z" },
    { "seq": 1000, "event": "started", "at": "2026-08-21T11:08:44.000Z" },
    { "seq": 2000, "event": "tool_called", "at": "2026-08-21T11:08:51.000Z" },
    { "seq": 2001, "event": "tool_called", "at": "2026-08-21T11:09:30.000Z" },
    { "seq": 3000, "event": "gate_opened", "at": "2026-08-21T11:10:12.000Z" }
  ]
}

6. The storyboard card waits

The run stops at the storyboard. gate_opened is the last event, and the run carries one entry in pending_approvals.

{
  "data": {
    "id": "6f31c07d-...",
    "trigger": "workflow",
    "status": "processing",
    "conversation_id": null,
    "generation_spend_cap_credits": 0,
    "pending_approvals": [
      {
        "gate_id": "44b1d0e7-...",
        "summary": "storyboard render x 2",
        "credits": 96,
        "expires_at": "2026-08-21T11:25:12.000Z",
        "approve_url": "https://api.roasos.com/v1/agent-runs/6f31c07d-.../gates/44b1d0e7-.../approve"
      }
    ]
  }
}
FieldMeaning
gate_idThe identifier of the card. Use it on the approve path and on the decline path.
summaryThe board and the number of variants.
creditsThe price of the whole board. roasOS quotes each compiled request on the worker and adds the quotes together.
expires_atThe card stops after 15 minutes. A card that expires renders nothing and charges nothing.
approve_urlWhere to say yes. A remix writes no thread, so the value is the approve path itself. A run in a thread names its card in roasOS instead.

The default of generation_spend_cap_credits is 0, so a remix that says nothing about the cap always stops here. This is by design. Refer to Let the run render without you for the unattended form.

7. Approve the card

A run started from a workflow writes no thread, so there is no card in roasOS for a person to press. Approve it over REST instead.

curl -X POST https://api.roasos.com/v1/agent-runs/6f31c07d-.../gates/44b1d0e7-.../approve \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: remix-glow-serum-001-approve" \
  -H "Content-Type: application/json" \
  -d '{ "generation_spend_cap_credits": 120 }'
{
  "data": {
    "gate_id": "44b1d0e7-...",
    "run_id": "6f31c07d-...",
    "status": "approved",
    "decided_at": "2026-08-21T11:12:40.000Z",
    "follow_up_run_id": "a71e5b28-..."
  }
}

The approval starts a second run. follow_up_run_id is that run. Poll it exactly as you polled the first one. It carries trigger: "api" and the same skill_id, so the render stays attributable to the pack skill that proposed it.

roasOS composes the text of the follow-up run from the approved card, and never from the caller. A run with no thread holds no history, so a model can recover no storyboard id from it.

The approval spends on your key. It needs an Idempotency-Key. The price on the card stays inside max_credits_per_request on the key, and the follow-up run stays inside the daily budget and the monthly budget of the key. Refer to Spend caps and approvals.

The approval quotes and confirms the follow-up run in the one call. You send no quote_only value and no quote_id here.

Approve is a REST operation only. It is not an MCP tool, and it will not become one. A connected model may decline an approval. It must never approve its own spend. Refer to Approving spend is never a tool.

8. Read the renders

The follow-up run starts one generation for each compiled request. Each generation is an ordinary job.

curl "https://api.roasos.com/v1/jobs?limit=10" \
  -H "Authorization: Bearer roasos_sk_..."

Poll each job until the status is completed, failed or canceled. Read the file at GET /v1/jobs/{id}/result. The URL is immutable. Refer to Jobs.

Let the run render without you

Set generation_spend_cap_credits above the price of the board. The run then approves the storyboard card itself, and the render starts in the same run.

curl -X POST https://api.roasos.com/v1/workflows/remix \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: remix-glow-serum-002" \
  -H "Content-Type: application/json" \
  -d '{
    "discover_item_id": "6f3a9c21-4b0e-4c3a-9f52-1d7a8c0e5b44",
    "product_id": "5e6b3311-7a2c-4f19-b3d8-0c41e7f92a63",
    "avatar_id": "9c17ab42-0b53-4d1e-8f7a-2c9b6e40a115",
    "variants": 2,
    "max_credits": 25,
    "generation_spend_cap_credits": 120,
    "quote_id": "e2c74a10-..."
  }'

The events then show the card and its approval together, and pending_approvals stays empty.

{
  "data": [
    { "seq": 3000, "event": "gate_opened", "at": "2026-08-21T11:10:12.000Z" },
    { "seq": 4000, "event": "gate_auto_approved", "at": "2026-08-21T11:10:12.000Z" },
    { "seq": 5000, "event": "generation_started", "at": "2026-08-21T11:10:14.000Z" },
    { "seq": 5001, "event": "generation_started", "at": "2026-08-21T11:10:15.000Z" },
    { "seq": 6000, "event": "settled", "at": "2026-08-21T11:13:51.000Z" }
  ]
}

What the run must satisfy first

The run approves a storyboard card by itself only when every condition below is true. In all other conditions the card waits, exactly as in step 6.

  1. The price of the board is inside the credits that remain in generation_spend_cap_credits.
  2. The price is inside auto_approve_up_to_credits on your key.
  3. roasOS priced every compiled request on the worker. A partial price set never auto-approves, because one request would run at the approved price and another would ask for a new one.
  4. The board compiles to 8 requests or fewer. Count the requests as shots, multiplied by variants, multiplied by matrix cells.
  5. The board does not use the first-frame pipeline. That pipeline stops for a person to approve each frame, which is the reason it exists.

The price on the card is the price roasOS charges. Each compiled request carries its own worker quote, and the render runs under that quote.

A worker quote holds for 10 minutes, and a card holds for 15. An unattended run therefore dispatches inside the quote window, which it does in seconds. A card that a person approves late can lose a quote; the run then prices that request again.

Price

A remix has no price of its own. Two meters run under it.

WhatMeter
The thinking of the runmax_credits. roasOS charges the real tokens and refunds the rest.
Each rendered clipThe price of the model the board compiled to, quoted before dispatch and bounded by generation_spend_cap_credits

The analysis inside the run reads the ad; it renders nothing, and it carries no separate line. Compare it with POST /v1/workflows/analyze, which is a priced operation of its own.

roasOS reserves credits_max at the confirm step. It settles the run when the run stops, and it refunds the part the run does not use. Refer to What a run costs.

Limits

  • One remix reads one source ad.
  • variants is 1 or 2. A larger fan-out belongs in the roasOS storyboard panel.
  • A board of more than 8 compiled requests always waits for a person.
  • The run holds one product. Cast a second product in a second remix.

Errors

StatusCodeCause
400validation_errorTwo sources, no source, or a field outside its range
400discover_source_not_allowedA Discover creative in ad_url or in source_generation_id
400idempotency_key_requiredThe Idempotency-Key header is absent
400quote_requiredThe body has no quote_only value and no quote_id
400spend_cap_exceeds_policyThe ceiling is above the maximum price for one request of the key
402approval_requiredThe ceiling is above the unattended limit of the key
402insufficient_creditsThe balance does not cover the ceiling
404—The product, the avatar, or the source is not in your workspace
410quote_expiredQuote again under a new idempotency key
429daily_credit_budget_exceeded, monthly_credit_budget_exceededThe budget of the key has no space
503skill_store_unavailableroasOS cannot read the pack skill at this time

Refer to Errors.

From an agent

The MCP tool is roasos_remix_ad. It obeys the same quote rule as every paid tool.

An agent can start a remix and read its run. An agent can decline an approval. An agent can never approve one. Refer to Connect an AI agent (MCP).

On this page