A failed Format run webhook still has the receipt: salvage artifacts
When a Sume Format run fails, the webhook has status ERROR but payload is still the full receipt, with artifacts and output_error. Read them before you retry.

A failed Sume Format run still delivers a webhook with status: "ERROR", and payload is still the full receipt. That receipt can hold artifacts[] and an output_error, so read them before you re-queue. A run that rendered part of a job may have finished media you can keep.
What the failure delivery contains
The envelope error is a copy of payload.error. Its code is usually specific, such as output_schema_unsatisfied; if not, it is the generic format_run_failed. The envelope status is binary, so branch on outcome: ok, degraded or error.
| outcome | Meaning | First action |
|---|---|---|
| ok | Completed with usable output | Ship payload.output |
| degraded | Completed, real media, output null | Read output_error; review artifacts |
| error | Run failed; receipt still included | Read artifacts and error before retry |
Retrying without paying twice
You pay for generation that finished before a failure; a later failed step does not refund it. So a retry that starts from scratch buys the finished parts again.
If the run left artifacts and a thread, a new run with previous_run_id continues the same conversation, and the agent can redo one part and keep the rest. The continuation is a new run with a new id, its own spend cap and its own webhook. A run that failed with no artifacts cannot be continued (400 previous_run_not_resumable), so start fresh in that case.
- Bind the same
output_schemaon the continuation; it is per run. - Use a new
Idempotency-Keyfor the retry, because the old key replays the old receipt. - Failed deliveries are separate from failed runs: if your endpoint was down, the run is still
completedand you fetch it fromresult_url.
A handler that does not lose the receipt
Store the whole envelope before you branch on it. A handler that reads payload as an object will throw when a receipt is over 1 MiB, because Sume then sends payload: null with error.code of payload_too_large and a result_url to fetch it from.
Dedupe on request_id, which equals the run id and repeats on retries, and order deliveries by created_at. A failed run delivers once, like a success, and a canceled or skipped run delivers nothing.
Tradeoff
Salvaging partial output saves money but needs your own review step, since a part of a video is not a finished ad. Decide up front which fields count as a deliverable.
Sources
Related posts
More in Formats
- Format io is null on older Formats: pick by your own input kind
On Sume's Format list, the io block is null for Formats saved before the field existed. Do not route on it alone; read input_kind and output_kind when present.
- Sume Format output_schema: strict false does not loosen the rules
Setting strict to false in a Sume Format output_schema does not relax the OpenAI-strict subset. Fix the schema instead. Responses-style text.format is refused.
- 400 previous_run_format_mismatch: continue a run on its own Format
Continuing a Format run on a different Format returns 400 previous_run_format_mismatch. Call the Format where the run started, or start a new run.
- Sume Format run idempotency key: order id plus version, not uuidgen
Derive the Sume Format run Idempotency-Key from your order id plus a version. A fresh uuidgen per request makes the header do nothing and double-bills retries.
Written by Sume