Retry a Seedance submit safely: Idempotency-Key on /v1/videos
A timed-out POST to /v1/videos can create two paid jobs. Send an Idempotency-Key and a replay returns the original job. Python example included.

Send an Idempotency-Key header on every POST /v1/videos. The Sume docs say this makes retries safe: a replay returns the original job instead of creating a second one. Without it, a request that times out on your side may still have reserved money on the server.
This matters most for automation: a workflow tool that retries on a timeout is exactly the case where a duplicate job appears.
Why does a timeout cost money?
Video submits are asynchronous, so the server may accept the job and reserve funds before your client sees the 202. Sume reserves the provider list price times 1.25 on submit, per the docs. If your retry code POSTs again with no key, you now have two jobs and two reservations.
How do I pick the key?
Derive it from your own record, not from a random value generated per attempt. A key built from the row id and the intent ("order-1042-hero-clip") stays the same across retries, which is the point. A fresh uuid4 on every attempt defeats it.
In practice a good key has three parts: what you are making, for whom, and which version. For example a catalog id, a variant number and a date. When the business intent changes, the key changes. When only the transport failed, the key stays.
Also log the key next to the job id. If a person later asks why there are two clips, the log answers the question at once.
What does a safe submit look like?
This Python submits with a stable key and retries on network errors. Pass the same key each time.
A few details in that code are deliberate. The timeout is set so a hung connection ends instead of blocking a worker. Exponential backoff spaces the attempts at one, two and four seconds. And raise_for_status turns a 4xx or 5xx into an exception, so a validation error such as a bad ratio is retried only up to the loop limit; in real code, stop immediately on a 400, because a malformed body will not become valid by waiting.
Do not retry 4xx responses other than a rate limit. Retry network errors, timeouts and 5xx.
import os, time, requests
URL = "https://api.sume.com/v1/videos"
H = {
"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
"Idempotency-Key": "order-1042-hero-clip",
}
body = {"model": "seedance-2.5", "prompt": "Slow push-in on a ceramic mug",
"duration": 6, "resolution": "720p", "aspect_ratio": "16:9"}
for attempt in range(4):
try:
r = requests.post(URL, headers=H, json=body, timeout=30)
r.raise_for_status()
print(r.json()["id"])
break
except requests.RequestException as e:
print("retry", attempt, e)
time.sleep(2 ** attempt)What are the limits of this?
The docs state the behavior in one line: send the header and a replay returns the original job. They do not document how long a key is remembered, so do not assume it lasts forever; if you change the body, use a new key. A key protects the submit only; polling is a GET and is always safe to repeat. For failure accounting see whether failed jobs cost money.
To test the behavior safely, submit a small 480p clip twice with the same key and the same body, and compare the two job ids. The docs say a replay returns the original job, so they should match. Do that once in a development workspace before you rely on it in a pipeline.
Sources
Related posts
More in Developers
- Seedance webhook on Sume: callback_url and a Python signature check
Get a signed webhook when a Seedance or Kling job ends: send callback_url to /v1/videos, verify the HMAC in Python, and keep polling as the fallback.
- Number every Shorts series episode on screen with caption cues
YouTube added Shorts series with seasons and episodes in September 2026, per air.io. Burn Episode N onto each clip with Sume caption cues, in Python.
- Shotstack render statuses vs Sume job statuses: a map
Shotstack renders go queued, fetching, rendering, saving, done or failed. Sume jobs go queued, processing, completed, failed or canceled. Map them in code.
- Should you wait for Veo 4? Build on a swappable model id instead
No Veo 4 date, id or price page has been reported. How to ship video work now with the model id in config, and what a swap needs.
Written by Sume