Promise.allSettled for a wave of Sume jobs: keep the partial wins
Promise.all throws away nine good Sume videos when one job fails. Use Promise.allSettled over a wave sized to your plan's concurrency, in 30 lines of Node.

The wave
Sume admits only so many generations at once: concurrency is 1 on Free, 4 on Pro, 8 on Startup and 20 on Scale, and submits beyond that wait in a queue whose default size is the larger of 3 and five times the concurrency. Past the queue you get 429 queue_full. The generation limits object even returns a wave_size_hint.
So a batch of 40 jobs should go out in waves, not as 40 simultaneous submits. Inside a wave you want every job's outcome, and one failure must not hide the rest.
Why not Promise.all
Promise.all rejects on the first rejection and you lose the other results in your handler, even though those jobs keep running and billing on Sume's side. Promise.allSettled always waits for all and gives each result a status of fulfilled or rejected.
A runnable wave
Replace the job ids and run with Node 18+. The poll function returns the final status for one id; a thrown error becomes a rejected result you can log and retry later.
const H = { Authorization: "Bearer " + process.env.SUME_API_KEY };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function poll(id) {
for (;;) {
const r = await fetch("https://api.sume.com/v1/jobs/" + id + "/status", { headers: H });
if (!r.ok) throw new Error(id + " HTTP " + r.status);
const { data } = await r.json();
if (data.terminal) return { id, status: data.status };
await sleep((data.next_poll_after_seconds ?? 5) * 1000);
}
}
const ids = process.argv.slice(2);
const results = await Promise.allSettled(ids.map(poll));
for (const r of results) {
console.log(r.status === "fulfilled" ? r.value : "error: " + r.reason.message);
}After the wave
- Fetch results only for fulfilled entries whose status is completed.
- For failed jobs, resubmit with a new Idempotency-Key; the old key points at the old attempt.
- Save this as a .mjs file: it uses top-level await, which Node supports in ES modules.
Sources
Related posts
More in Developers
- provider_submission_failed 502: Sume could not start the job, retry
provider_submission_failed is a 502 meaning the job never started. By default it is retryable with retry_after_seconds 30 and next_action retry_later.
- Pydantic v2 models for the Sume /v1/videos poll response
Typed Pydantic v2 models for POST and GET /v1/videos: five status literals, an optional error string, a url list, and a guard that stops a bad status early.
- Python async generator that yields Sume job status until terminal
Write an async generator in stdlib Python that polls /v1/jobs/:id/status, honours next_poll_after_seconds, and stops at a terminal status. No SDK needed.
- Python: price a Seedance 2.5 clip from seconds and resolution
A 17-line function turns resolution and seconds into video tokens and a Sume price: 4 s at 480p is $1.07, 30 s at 1080p is $42.65.
Written by Sume