createSumeClient timeout is 10 minutes per request: tune it for polls
The Sume SDK client waits up to 10 minutes on each HTTP request, so one hung status poll can stall waitForJob for 10 minutes. Use a short-timeout client.

createSumeClient from @sume-com/sdk@0.2.0 sets a per-request timeout of 10 minutes by default (timeout: 600000). That is the limit on one HTTP request, not on a job, and it is far too long for a status poll. If a poll connection hangs, waitForJob sits there for up to 10 minutes before the request aborts, no matter what deadline you gave the wait itself. For polling, build a client with a short timeout, such as 30 seconds, and keep a separate client for submits.
Pass timeout: 0 to disable the per-request limit entirely. That is rarely what you want. The SDK run helpers page documents the job and run deadlines, which are separate numbers: 20 minutes for waitForJob, 10 minutes for waitForRun, and 20 minutes for subscribeFormatRun.
Three clocks that are easy to confuse
A wait has three independent timers. The request timeout bounds one call and applies afresh to each retry attempt. The wait timeout bounds the whole loop. The server-side bounded wait on a submit with mode: "sync" or "subscribe" is capped at 30 seconds and describes how long the API holds the HTTP request open, not how long the job may run (Jobs and results).
The practical consequence is a floor. A client used for a sync submit needs a request timeout comfortably above 30 seconds, or it will abort a request the server is still holding open. A client used only for polls and status reads can be much stricter.
| Timer | Default | What it bounds |
|---|---|---|
| Client timeout option | 10 minutes | One HTTP request, reset per retry attempt |
| waitForJob timeout | 20 minutes | The whole poll loop for a job |
| waitForRun timeout | 10 minutes | The whole poll loop for a run |
| Server sync and subscribe wait | 30 seconds max | How long a submit request is held open |
Two clients, two budgets
The snippet gives polls a 30-second request limit and submits 60 seconds, then waits with the poll client. A caller-supplied signal is combined with the timeout, so aborting your own signal still cancels the in-flight request immediately, and an abort you cause is never retried.
import { createSumeClient, generateImageV1, waitForJob } from "@sume-com/sdk";
const apiKey = process.env.SUME_API_KEY ?? "";
if (!apiKey) throw new Error("set SUME_API_KEY");
const submitClient = createSumeClient({ apiKey, timeout: 60_000 });
const pollClient = createSumeClient({ apiKey, timeout: 30_000, maxRetries: 2 });
const { data, error } = await generateImageV1({
client: submitClient,
headers: { "idempotency-key": crypto.randomUUID() },
body: { prompt: "Matte black bottle on marble, soft window light", mode: "async" },
});
if (error || !data) throw new Error(JSON.stringify(error));
const job = await waitForJob(data.data.request_id, {
client: pollClient,
signal: AbortSignal.timeout(15 * 60_000),
});
console.log(job.status);What not to change
- Do not set the request timeout to match the job length. A request is one poll, and a ten-minute job is hundreds of short polls.
- Do not retry a submit without an
Idempotency-Key. The client only replays a POST that carries one, so a timeout on a keyless submit is surfaced to you instead. - Keep
maxRetriesat 2 or higher for polls, since read failures are the case retries exist for. - Treat a timeout on a submit as unknown outcome: read your job list or retry with the same key rather than submitting again with a new one.
Related posts
More in Developers
- CrewAI conversational flows: confirm cost before a Sume render
In a CrewAI chat flow, have the step call Sume with dry_run first and ask the user to confirm the cost.
- Cursor Security Review bot on a Sume webhook handler: what to find
Cursor added a Security Review bot on Sep 23. A webhook handler for Sume should pass seven checks: raw body, timestamp window, rotation, empty secret and more.
- Cursor self-hosted machines can't take Sume webhooks on a private URL
Sume rejects localhost, private-network and non-HTTPS webhook URLs. An agent on a self-hosted machine should poll status_url or use a public HTTPS receiver.
- Demand Gen copy limits: 40-character headlines, one at 30 or fewer
Demand Gen allows 40-character headlines (one must be 30 or fewer), 90-character descriptions and 10-60 second videos. A checker script plus the Sume lengths.
Written by Sume