One bad item in a 100-item Format bulk request: 400, nothing runs

A Format bulk create validates every item first. One invalid item returns 400 with details.index and queues nothing.

5 min readSume
All posts

What happens if one item in a 100-item Format bulk request is invalid? The whole create fails with 400 invalid_request and details.index pointing at the bad item, before a queue exists, so nothing is dispatched and nothing is billed. Fix the item and send the batch again.

That behavior suits a micro-drama season. You might queue 40 episodes overnight, and you want a typo on episode 27 to stop at the door rather than surface at 3 a.m. with 26 renders already spent.

The envelope

POST /v1/formats/{handle}/{slug}/bulk-runs takes exactly two top-level keys that matter: concurrency, an integer from 1 to 16, and items, 1 to 100 entries in order. Each item has the same body as a single run. Unknown top-level fields are rejected, and an envelope without items is a 400, not an empty queue. The key needs the formats:write scope.

curl -sS -X POST "https://api.sume.com/v1/formats/acme/episode-pack/bulk-runs" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: season1-batch-1" \
  -d '{"concurrency":4,"items":[
    {"instruction":"Episode 1","input":{"beat":"hook"}},
    {"instruction":"Episode 2","input":{"beat":"reveal"}}
  ]}'

What makes an item valid

Each item must name at least one of instruction, input, previous_run_id or attachments. An item of {} or {"input": {}} is the failure case. The check runs for every item at create time, which is why the error carries an index.

Bulk create rules (Sume docs read 2026-10-07)
RuleValue
Items per request1-100
concurrency1-16
Item with nothing to run400 invalid_request, details.index
WebhookPer item; the queue has none
Replay of a spent Idempotency-Key202 with the old queue

Operational notes

Mint a fresh Idempotency-Key per batch. If you replay a spent key you get 202 with the old queue, which looks like success but is not your corrected batch.

Progress is polled at GET /v1/format-run-queues/{id}. The queue status completed means every item is terminal, not that every item succeeded, so branch on counts.failed. To cancel a child, use POST /v1/format-runs/{run_id}/cancel; there is no cancel-queue endpoint.

Validate on your side first: loop the list, assert each item has one of the four fields, and only then post. The server check is a safety net, not a linter.

Handling the failure

Because nothing is queued on a 400, the fix is cheap: read details.index, correct that one item, and resend the whole request. Do not split the batch to work around it; validate items in your own code first, using the same rules the API applies, so the 400 never happens in production.

  • The error names the first bad item by index.
  • Resend the full list after you fix it.
  • Concurrency is 1 to 16 and items are 1 to 100.

Validating before you send

A pre-flight check in your code saves a round trip. Loop over the items and assert that each has at least one of instruction, input, previous_run_id or attachments, that the list has between 1 and 100 entries, and that concurrency sits in the 1 to 16 range. The same check doubles as a test for your episode builder.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume