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
| Key | Notes |
|---|---|
instruction | Prose 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. |
input | The 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_schema | mobidoo/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_usd | 120 per item — the ceiling for that one child run, not for the queue. Twenty items can spend twenty caps. |
communication | Per-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_urlis per item; there is no queue-level callback. Pollstatus_url(GET /v1/format-run-queues/{queue_id}) for progress. - Queue
completedis not “all succeeded.” It means every item is terminal. Branch oncounts.failedandcounts.canceled. - Read failures on the child. Take
items[i].run_idandGET /v1/format-runs/{run_id}— the queue item only carries a coarseformat_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. Withfull_videoonly there are no scene ids to name.
Next
- Bulk runs — platform queue contract, polling, errors
- Live Commerce API — single run, clip schema, clip retry
- Best practices — create → receipt → clip-retry on one thread
- Structured output — schema binding rules

