Sume sync mode: set your client timeout above 30 s, then poll

Sume sync waits at most 30 seconds. If your HTTP client gives up at 30 s too, you lose the job id. Use a 45 s timeout, then poll and reuse the Idempotency-Key.

4 min readSume
All posts

Two clocks racing

In sync mode (also spelled subscribe) Sume holds your submit response open for up to wait_timeout_seconds, which is clamped to 0 through 30. If the job is not done by then, the response still arrives, with sync.timed_out true and the job id in the body, and you continue by polling.

That is only safe if your own HTTP client waits longer than the server does. A client timeout of 30 seconds, or a load balancer idle timeout of 30 seconds, can cut the connection a moment before Sume answers. You then hold no job id for a job that exists and is billing.

The safe order

  • Set the client timeout to the wait plus a margin: 45 seconds for a 30-second wait.
  • Send an Idempotency-Key on the submit, generated before the first attempt and stored.
  • If the call fails with a timeout or a network error, retry the submit with the same key. You get the original job back rather than a second paid one.
  • If sync.timed_out is true, poll status_url until terminal. Never submit again as a new job.

A runnable example

It submits with a 45-second AbortSignal, then prints the sync object, whose timed_out flag says whether the wait ended early. Node 18+, saved as sync.mjs. The key is fixed in the script on purpose so you can re-run it and see the same job.

const key = "demo-sync-2026-10-05-a";
const res = await fetch("https://api.sume.com/v1/images", {
  method: "POST",
  signal: AbortSignal.timeout(45_000),
  headers: {
    Authorization: "Bearer " + process.env.SUME_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": key,
  },
  body: JSON.stringify({ model: "sume/auto", prompt: "a red kettle on a wooden table", mode: "sync", wait_timeout_seconds: 30 }),
});
const body = await res.json();
console.log(res.status, JSON.stringify(body.sync ?? body.data?.sync ?? "finished inside the wait"));

Edge cases

Reusing a key with a changed body returns 409 idempotency_conflict, so keep the payload identical on retry. If two retries overlap, the second may see 409 idempotency_key_in_use for about a second; wait and retry. sync.capacity_exhausted tells you the wait ended because the workspace had no free slot, which is a queueing signal, not a failure.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume