Retry a Sume video submit safely: Idempotency-Key and the 409 conflict

Send the same Idempotency-Key and the same body to retry a Sume video submit without a second charge. A different body under the same key returns 409.

4 min readSume
All posts

Add an Idempotency-Key header to POST /v1/videos. If a network error hides the response, resend the same key with the same body, and you get the original job back instead of a second one. If you reuse the key with a different body, Sume answers 409, so a typo cannot silently start a different job.

This matters most for long and expensive jobs, where a duplicate would hold the reserve twice.

What the key does

The docs say an idempotent replay gets the same route and the same price, because the sume/auto resolution is a pure function of the normalized request and the catalog version. The key ties the request to one job.

The key is yours to choose. Use something stable and unique, like an order id plus the shot number.

Idempotency behavior on /v1/videos, read 2026-10-05
RequestResult
new key, any bodynew job, 202
same key, same bodythe original job
same key, different body409 conflict
no keya new job every time

A retry in Python

The script retries the submit up to three times on a network error and keeps the same key for each attempt. It stops on an HTTP error, because a 400 or 402 will not change on a retry.

import json, os, time, urllib.error, urllib.request

body = json.dumps({"model": "gemini-omni-flash-1.1",
    "prompt": "A paper boat drifting down a rain gutter",
    "duration": 5, "resolution": "720p"}).encode()
headers = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
    "Content-Type": "application/json", "Idempotency-Key": "boat-shot-001"}

for attempt in range(3):
    req = urllib.request.Request("https://api.sume.com/v1/videos",
        data=body, headers=headers, method="POST")
    try:
        with urllib.request.urlopen(req, timeout=60) as r:
            print(json.load(r))
            break
    except urllib.error.HTTPError as e:
        print(e.code, e.read().decode())
        break
    except OSError:
        time.sleep(2 ** attempt)

Which errors to retry

Retry only when you got no response. A 402 insufficient_credits means the wallet is below the reserve, so add credit first. A 400 means the request is invalid, and the same request fails again. A 429 is rate limiting, so wait before the next try.

A 502 means the provider submission failed, and a retry with the same key is reasonable.

Key hygiene

Never reuse a key for a new shot, even a similar one, or you will get the old job or a 409.

  • Build the key from your own record id.
  • Keep the body byte-for-byte the same on a retry.
  • Store the key with the job id.
  • Change the key when you change the prompt on purpose.

Related posts

More in Developers

All Developers posts

Written by Sume