Mobidoo

Bulk runs

Mobidoo runs live-commerce two ways. The Live Commerce API page covers the single-run, clip-typed path: one POST …/runs, a receipt with opening[] / middle[] / closing[], and thread-based clip retry.

This page covers the other one: a sheet-driven batch. One row of the broadcast sheet becomes one item, the whole sheet becomes one POST …/bulk-runs, and the schema is trimmed to the only field the batch consumes — full_video. It is the shape used for the 2026-08-28 HBS No.45–65 batch, reproduced here unabridged so your backend can build the same body.

The clip schema is not replaced. Keep using mobidoo/live-commerce/v1 when you want typed clips and per-scene retry.

Workspace key

Same rule as every Mobidoo Format call: use a Mobidoo team workspace API key (created under the Mobidoo team, not a personal key). A personal key calling mobidoo/live-commerce fails with 403 workspace_key_required — see Team Formats need a team key.

The key needs formats:write to create the queue and formats:read to poll it. Scopes cannot be added to an existing key — mint a new one.

Not in the Mobidoo workspace yet? Request an invite on Slack to 허채원 (Chase Huh), or email chase@sume.com — see Workspace access.

The call

Keep the body in a file; it is far too long for a shell heredoc once every row carries its own VO.

Mint a fresh Idempotency-Key per batch ($(uuidgen)). Replaying a spent key returns 202 and the old queue instead of starting a new one.

The envelope

bulk-runs-body.json is two keys. Everything else lives inside each item.

The 2026-08-28 batch sent concurrency: 2 and 20 items: HBS No.45 through No.65, with No.50 skipped because that row had no finished draft. Skip rows client-side — there is no “empty item” to send. Item order is the order you submit; items[i].index on the receipt is that position, so keep your own sheet-row ↔ index map.

Create returns 202 with a frq_… queue and the first concurrency items already running. Provenance for the batch above: queue frq_cfd22d14-68db-4aeb-9816-404a79f0badf, live-commerce v38, counts at create 20 total / 2 running / 18 queued. That queue belongs to the key that created it — you cannot GET it with yours.

Full envelope contract, limits (concurrency 1–16, items 1–100), queue receipt shape, and every error code: Bulk runs.

Item 0 — the raw body

Each item is exactly the body of a single POST …/runs. This is item 0 (sheet No.45) verbatim, only communication.webhook_url swapped for a placeholder. The other 19 items carry the same six keys with their own row's data.

What each key is doing

KeyNotes
instructionProse plus the raw sheet row. The tab-separated block is the sheet line as copied; the quoted block is the full approved VO. Nothing is pre-parsed — the Format reads it.
inputThe same row again as structured JSON, so your backend does not depend on the Format re-parsing the TSV. script.segments carries the VO as one long block, not per-cut objects.
output_schemamobidoo/live-commerce/desk-iamdry/v1, strict: false, required full_video only (SumeMediaFile#). A batch that only publishes the assembled cut should not ask for clip arrays it will not read.
primary_output_key"full_video".
generation_spend_cap_usd120 per item — the ceiling for that one child run, not for the queue. Twenty items can spend twenty caps.
communicationPer-item terminal webhook. Published here as https://example.com/hooks/format-run; point it at your own endpoint.

desk-iamdry/v1 is a per-request schema name, not a new partner contract. Binding it changes what that run returns; it does not rebase mobidoo/live-commerce/v1.

Both instruction and input restate the row on purpose. instruction is guidance, input is data — see what is carried, and mind the size limits in Size: two limits: input is rejected above 8 192 UTF-8 bytes, and each field is carried into the run at about 4 000 characters, silently.

After the 202

  • The queue has no webhook. communication.webhook_url is per item; there is no queue-level callback. Poll status_url (GET /v1/format-run-queues/{queue_id}) for progress.
  • Queue completed is not “all succeeded.” It means every item is terminal. Branch on counts.failed and counts.canceled.
  • Read failures on the child. Take items[i].run_id and GET /v1/format-runs/{run_id} — the queue item only carries a coarse format_run_failed.
  • Each child is an ordinary Format run, so a weak row can be repaired on its own thread with previous_run_id — but only when the body binds the clip schema. With full_video only there are no scene ids to name.

Next