Bulk virtual try-on videos for a catalog: 100 SKUs per queue

Queue up to 100 try-on runs in one POST: concurrency 1 to 16, one garment image per item, a spend cap each, and how to read the failures afterwards.

5 min readSume
All posts

Send one POST /v1/formats/{handle}/{slug}/bulk-runs with an items array of up to 100 Format-run bodies and a concurrency between 1 and 16. For try-on, each item is the same body you would send to a single run: an instruction and the garment image as an attachment. Sume keeps that many runs in flight and starts the next as one finishes, so a 100-SKU catalog is one request and one queue to poll.

Shoppers now meet try-on inside ChatGPT, which OpenAI launched on October 1 2026, and sellers are asking for the same preview on their own product pages. A queue is how you make that preview for every SKU without driving the fan-out from your laptop.

What does a bulk queue actually do?

Per the Bulk runs docs, a queue is a server-side list of ordinary Format runs, not a different engine. Each item is one sandbox, one agent turn and one run receipt. The create call returns 202 with a format.run_queue, and the first concurrency items are already running on that receipt when the list is longer than the window.

Three details matter for a catalog. The queue has no webhook, so poll status_url for progress or give each item its own communication.webhook_url. A bad item fails the whole create with 400 invalid_request and a details.index, before anything is dispatched. And queue status completed means every item is terminal, not that every item succeeded.

Bulk queue limits that matter for try-on, read 2026-10-03
FieldLimit or ruleWhat to do
items1 to 100 per queueSplit a larger catalog into several queues
concurrencyRequired, 1 to 16Start low; each child is a full run that spends money
Idempotency-KeyFresh per batch; replaying a spent key returns the old queueDerive it from the batch, for example season and batch number
Per-item capgeneration_spend_cap_usd on each itemSet one so no single SKU can run away
Queue webhookNone; per-item webhook onlyPoll the queue or arm each item
Queue status completedEvery item is terminalBranch on counts.failed and counts.canceled

How do you write the request?

Use the sume handle and the catalog slug, the same address as a single run. The docs show bulk with team handles and do not show a catalog example, so run a two-item queue first and confirm the receipt before you send a hundred.

Keep your SKU on your side. The docs say input is not echoed into the output, so map results back by the item index, which follows the order you sent.

import os
import requests

key = os.environ["SUME_API_KEY"]
skus = {"1042": "https://cdn.example.com/1042.jpg", "1043": "https://cdn.example.com/1043.jpg"}
items = [
    {
        "instruction": "9:16 virtual try-on of the attached garment: a creator changes into it.",
        "attachments": [{"type": "input_image", "image_url": url}],
        "generation_spend_cap_usd": 20,
    }
    for url in skus.values()
]
r = requests.post(
    "https://api.sume.com/v1/formats/sume/sume-virtual-try-on/bulk-runs",
    headers={"Authorization": f"Bearer {key}", "Idempotency-Key": "tryon-fw27-batch-1"},
    json={"concurrency": 2, "items": items},
    timeout=60,
)
r.raise_for_status()
q = r.json()["data"]
print(q["id"], q["counts"], q["status_url"])
for sku, item in zip(skus, q["items"]):
    print(sku, item["index"], item["status"], item["run_id"])

How do you read the results and the failures?

Poll GET /v1/format-run-queues/{id} until the status is completed, then branch on counts. For every item with a run_id, read GET /v1/format-runs/{run_id} for the receipt: primary_output_url and artifacts[] on success, error on failure. A child that failed carries only a generic format_run_failed on the queue item, so read the reason on the run receipt, not on the queue.

To retry only the failures, build a new queue from those SKUs with a new Idempotency-Key. The retry post walks through that.

  • Check one finished video against the garment packshot before you queue the other 99.
  • Use a fresh key per batch; the same key with a different payload is a 409.
  • Cancel a child with POST /v1/format-runs/{run_id}/cancel; there is no cancel for the whole queue.
  • A try-on preview does not certify fit; ChatGPT Try On is reported to make no size or fit promise either.

How do you keep a 100-item queue under control?

Treat the first queue as a test. Send two or three SKUs, wait for them to finish, and open each video next to its garment photo. The queue is a convenience for the mechanics, not a quality check. Then raise the window gradually: the concurrency field accepts 1 to 16, but each child is a full run that spends money, and workspace generation concurrency still applies to the children.

Keep a small table on your side: SKU, queue id, item index, run id, status, and the receipt's billed amount. The queue's items array keeps the order you sent, so the index is enough to join it back to your catalog.

What does it cost?

We do not quote a per-video price for the try-on Formats, because the docs do not publish one: a run's cost depends on what it generates, and the receipt reports usage.billable_amount_usd_micros against your generation_spend_cap_usd. The honest way to budget is a small first queue, read the billed amount on each receipt, and multiply. Cap each item so the worst case is known before you start. Metered rates are on the API pricing page.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume