Weekly specials video for every restaurant location: one bulk run
One bulk run of up to 100 Format runs makes a weekly specials video per location. Concurrency 1 to 16, per-item webhooks, and the counts.failed check.

A restaurant group that wants a weekly specials video for each location can queue them as one bulk run: a single POST that holds up to 100 ordinary Format runs, with 1 to 16 of them in flight at a time. Each location is one item. You poll one queue instead of babysitting a dozen calls.
What Sume does not do is know your menu. The recipe is a Format you saved, and the dish, price and photo for each location go in as input. Bulk runs only handle the fan-out.
What goes in each item?
An item has the same body as a single run on Create a run: at least one of instruction, input, previous_run_id or attachments. For specials, that means the location's dish, price and a photo URL in input, and a short instruction that says what to make. The input object takes up to 64 top-level keys, so one object per location is plenty.
Give every item its own communication.webhook_url if you want a callback, because the queue itself has none. Set generation_spend_cap_usd per item too, so one runaway location cannot eat the batch budget.
import json, os, urllib.request
locations = [
{"id": "mission", "dish": "Crab toast", "price": "$14", "photo": "https://example.com/mission.jpg"},
{"id": "harbor", "dish": "Clam chowder", "price": "$12", "photo": "https://example.com/harbor.jpg"},
]
items = [{"instruction": "Make this week's 9:16 special video. Show the price card.",
"input": loc, "generation_spend_cap_usd": 10} for loc in locations]
body = {"concurrency": 4, "items": items}
key = os.environ.get("SUME_API_KEY")
if not key:
raise SystemExit("set SUME_API_KEY")
req = urllib.request.Request(
"https://api.sume.com/v1/formats/yourgroup/weekly-special/bulk-runs",
data=json.dumps(body).encode(), method="POST",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json",
"Idempotency-Key": "specials-2026-w40"})
print(urllib.request.urlopen(req).read().decode())How do I know which location finished?
The 202 receipt is a format.run_queue with counts and an items[] array in the same order you submitted. Item 0 is your first location, so keep a list of location ids by index. Each item gets a run_id once it starts, and GET /v1/format-runs/{run_id} returns the full receipt with the output.
Poll status_url, or GET /v1/format-run-queues/{queue_id}. The queue is completed when every item is terminal, and that is where people go wrong.
Why is completed not the same as succeeded?
A queue marked completed can contain failed and canceled items. Read counts.failed and counts.canceled before you tell anyone the specials are ready. A failed item shows format_run_failed, and the reason is on that child's run receipt, not on the queue row. A child that could not even start has run_id: null and a create-run error such as format_run_failed_to_start, and the rest of the queue keeps going.
If you need typed results rather than a paragraph, bind an output_schema per item so each receipt carries the video URL in a known field. Structured output explains the rules, including that every property must be listed in required and optional values are nullable unions.
What are the traps?
- Mint a fresh
Idempotency-Keyfor each weekly batch. A replayed key with the same payload returns202and the old queue, and the same key with a changed payload is409 idempotency_conflict. A key likespecials-2026-w40is both readable and unique per week. - One bad item fails the whole create with
400 invalid_requestanddetails.index, before any queue exists. Nothing is dispatched, so you can fix item 7 and resend. - There is no cancel-queue or list-queues endpoint. To stop one location,
POST /v1/format-runs/{run_id}/cancelon that child, which frees its slot. - Child runs still obey wallet balance and workspace generation concurrency, so a window of 16 does not mean 16 simultaneous renders if your plan allows fewer.
- The key must carry
formats:writeto create andformats:readto poll. A service-account key cannot create runs.
For a 12-location group a window of 4 to 6 is a sensible start. Check the queue after the first few items finish, look at one output, and only then leave the rest overnight. The daily price-change variant, where a single clip is re-captioned each day, is covered in Restaurant daily special video.
Sources
Related posts
More in Use cases
- Review a creator clip's transcript before reusing it as a paid ad
Get a creator clip's transcript for $0.01 per audio minute with video inspect, then flag risky claims with your own word list before the clip becomes an ad.
- Rightmove AI photo rules: light touch vs enhanced edits
Rightmove's January 2026 guidelines allow AI-edited property images only if not misleading, labelled, and paired with current, accurate images of the room.
- Rightmove watermark rules: white, 30% opacity, quarter size
Rightmove allows only white, translucent watermarks, at most a quarter of the image and 30% opacity or lower. Check the rule before you brand property photos.
- Run one video prompt across five Sume models: a Python bake-off
Submit the same prompt to five Sume video models, choose each model's resolution from the catalog, and compare cost and time. Runnable code under 30 lines.
Written by Sume