Retry Sume 429s in TypeScript: a fetch wrapper that obeys retry-after
A small fetch wrapper for the Sume API: retry 429 only when the request is a GET or carries an Idempotency-Key, wait retry-after, and never loop on queue_full.

Retry a Sume 429 only when the request is safe to repeat, wait the number of seconds in retry-after, and cap the attempts. A safe request is a read, or a paid submit that carries an Idempotency-Key; the docs say not to retry unsafe submits without one.
The wrapper
It returns the 429 to the caller when the request is unsafe or attempts run out. It falls back to exponential waiting when retry-after is absent.
export async function sumeFetch(
url: string,
init: RequestInit = {},
tries = 4,
): Promise<Response> {
const headers = new Headers(init.headers);
const safe =
(init.method ?? "GET") === "GET" || headers.has("idempotency-key");
for (let i = 0; ; i++) {
const res = await fetch(url, init);
if (res.status !== 429 || !safe || i >= tries - 1) return res;
const wait = Number(res.headers.get("retry-after")) || 2 ** i;
await new Promise((r) => setTimeout(r, wait * 1000));
}
}429 has two meanings
rate_limited is the request budget and clears with time. queue_full means the workspace has no accepted generation capacity left; the docs say to stop adding work, let jobs finish or cancel queued ones, then retry with the same idempotency key. Blind retries against queue_full just hold the line, so in production read error.code before sleeping and route queue_full to your scheduler.
What to log
Log ratelimit-remaining on every response and the x-sume-request-id header on every failure; request ids are safe to share with Sume support. Never log the API key or signed URLs.
| error.code | Meaning | Client behavior |
|---|---|---|
| rate_limited | Request volume over the key's budget | Wait retry-after, retry safe requests |
| queue_full | No accepted generation capacity left | Stop submitting, drain or cancel, then retry with the same key |
Sources
Related posts
More in Developers
- Sume reserve, capture, refund: what your cost ledger should mirror
Sume reserves the estimate at submit, captures it on success and releases it on failure or cancel. Mirror the three states or cost reports will double count.
- Sume SDK returns {data, error}, not exceptions: an unwrap helper
Generated @sume-com/sdk operations resolve with data, error and response instead of throwing. Wrap them in an unwrap helper that throws a typed error.
- Where the Sume TypeScript SDK runs: Node 18+, Bun, Deno and Workers
@sume-com/sdk has no runtime dependencies and needs only fetch and WebCrypto. Install it, create a client, and know which options and helpers it adds.
- Sume video callback_url must be HTTPS: a webhook instead of polling
POST /v1/videos accepts callback_url, which must be HTTPS. Event names, the signature header, retries, and when a poll loop is still the safer choice.
Written by Sume