SDK waitForJob reads per minute: the 2-second floor, and 10 jobs
The Sume SDK polls a job at least every 2 seconds, and a longer next_poll_after_seconds wins. That is up to 30 reads a minute per job. A webhook removes them.

With the SDK's default pollInterval of 2 seconds, waitForJob can make up to 30 status reads per minute for one job, and 300 per minute for ten jobs waited at once. The docs call 2 seconds a floor: when next_poll_after_seconds in the status payload asks for a longer time, that value wins, so the real count is usually lower. The numbers matter because a 30-second video job and a 10-minute video job both start polling the moment you submit.
The defaults
The SDK docs list waitForJob with a default timeout of 20 minutes, a pollInterval of 2 seconds and an onStatus callback on every read, including the terminal one. A timeout throws SumeJobTimeoutError and does not cancel the job: it keeps running and billing, and the error carries jobId. Reads have their own rate-limit budget, separate from the budget for creates, so polling does not cause a 429 on your submits.
| Jobs waited at once | Reads per minute | Reads in a 10-minute wait |
|---|---|---|
| 1 | 30 | 300 |
| 5 | 150 | 1,500 |
| 10 | 300 | 3,000 |
| 20 | 600 | 6,000 |
Why you would not pay that
These are ceilings, not measurements. Honoring next_poll_after_seconds lowers them, and the helpers add jitter so clients that start together do not stay in phase. A 429 or 5xx on a status read means the read failed and not the job, and the helpers back off and poll again. createSumeClient itself retries 408, 429 and 5xx with exponential backoff and jitter, honoring retry-after.
The docs' own advice is to prefer a webhook where you can: a poll loop needs a timer and an open request per job in flight, and jobs usually take minutes. Build the receiver first and keep waitForJob as the fallback.
A sketch from the docs
This is the documented job helper. It submits with mode: "async" and a unique idempotency key, then waits client-side, so no HTTP request stays open.
import { createSumeClient, generateVideoV1, waitForJob } from "@sume-com/sdk";
const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });
const { data: submitted, error } = await generateVideoV1({
client,
headers: { "idempotency-key": crypto.randomUUID() },
body: { prompt: "Slow push-in on a ceramic mug", mode: "async" },
});
if (error) throw new Error(JSON.stringify(error));
const job = await waitForJob(submitted!.data.request_id, {
client,
onStatus: (status, snapshot) => console.log(status, snapshot.next_action),
});
console.log(job.status, job.result.artifacts);Failed is still a resolved wait
waitForJob resolves with the job record, not with /result. For failed and canceled jobs /result answers 409 job_not_completed, so the helper returns the record and you read status, result and error from it. Branch on job.status rather than wrapping the call in a try block and expecting an exception for a failed render.
Setting the options on purpose
The defaults suit a script that runs once. For a service, set the timeout to match what you are willing to hold a worker for, and keep the poll interval at or above the 2 second floor the SDK enforces. A tighter interval does not make the render faster, and it raises your read count.
A SumeJobTimeoutError carries the jobId. Catch it, store the id, and decide whether to wait longer or to move on. The timeout does not cancel the job; it only ends your wait. If you want to stop the job, call cancel, and remember that cancel works only before generation starts.
For high-volume work, prefer a webhook as the signal and leave waitForJob for scripts and tests.
- Floor of 2 seconds between status reads.
- Default timeout of 20 minutes.
- The error holds the
jobId; a timeout does not cancel.
When to skip the SDK wait
A long-lived service that holds a thread per job wastes workers on a wait that the platform can signal for you. In that case submit with async, store the job id, and let a webhook or a scheduled poll pick it up. The SDK wait is a convenience for scripts, notebooks and tests, where one process owns one job from start to end.
Whatever you pick, the read budget is generous, but it is still a budget. Read ratelimit-remaining and retry-after instead of counting your own requests, and spread polling across jobs with the interval the job envelope returns.
Sources
Related posts
More in Developers
- See every webhook attempt for a Sume video job: webhook.delivery
Did Sume reach your endpoint? Read webhook_delivery on the job and the webhook.delivery events: statuses pending to exhausted, last_error and attempt count.
- Seedance 2.5 API 'coming soon' on ModelArk: what to call today
ByteDance says Seedance 2.5 API access is coming via ModelArk. Sume lists seedance-2.5 now: id, limits, price, and how to keep a later switch cheap.
- Seedance 2.5 green-screen editing: swap a background on Sume
ByteDance and fal describe green-screen editing for Seedance 2.5. Sume does not expose that mode, but Omni edit swaps a background with one video_url request.
- Seedance 2.5 price per second: read it from the Sume catalog before Q4
Seedance 2.5 renders 4 to 30 seconds at up to 1080p on Sume. Read its live price from the catalog, then run one 4-second draft to get your real cost per second.
Written by Sume