GPT Image 2.5 can take 2 minutes: submit async, not sync, on Sume

OpenAI says complex GPT Image 2.5 prompts can run up to 2 minutes. Sume's image route blocks only 30 seconds, so send mode async and poll the job.

4 min readSume
All posts

OpenAI's image generation guide says complex prompts can take up to 2 minutes. On Sume, POST /v1/images blocks for at most 30 seconds, so a slow GPT Image 2.5 request can come back as a 202 job envelope instead of an image. Send mode: "async" from the start and poll the job, and your client handles every case the same way.

The mismatch in numbers

Sume is explicit that 30 seconds is a wait budget for the HTTP request and not a limit on the job. When the budget ends, the response is still a success and carries the job id. Check the status code: 200 is the image response, 202 is the job envelope. The docs name 4K, high quality and large n as the settings most likely to degrade to 202.

Image generation limits, read 2026-10-05
ItemValueSource
Complex prompt durationUp to 2 minutesOpenAI guide
Sume sync wait on POST /v1/imagesAt most 30 seconds, then 202Sume docs
Size ruleMultiples of 16, ratio 1:3 to 3:1, 655,360-8,294,400 pixelsOpenAI guide
Sume custom pixelsBoth edges multiples of 16, max edge 3840, ratio at most 3:1, 655,360-8,294,400 pixelsSume docs
Qualitylow, medium, high, xhigh, max, autoBoth

Submit async, then poll

GPT Image 2.5 is openai/gpt-image-2.5 (Flare) or openai/gpt-image-2.5-sunburst in the Sume catalog. The sketch sends the job with an idempotency key, reads the status_url from the 202 envelope, and polls it. Reuse the key on any retry of the submit, so a network failure cannot bill twice.

import asyncio, os
import httpx

async def main():
    headers = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
    body = {
        "model": "openai/gpt-image-2.5",
        "prompt": "Poster of a ceramic mug on a marble counter, soft window light",
        "quality": "high",
        "mode": "async",
    }
    async with httpx.AsyncClient(timeout=60) as client:
        r = await client.post("https://api.sume.com/v1/images", json=body,
                              headers={**headers, "Idempotency-Key": "poster-hero-001"})
        r.raise_for_status()
        env = r.json()
        env = env.get("data", env)
        for _ in range(60):
            s = (await client.get(env["status_url"], headers=headers)).json()
            s = s.get("data", s)
            if s.get("terminal"):
                print("done:", env["result_url"])
                break
            await asyncio.sleep(float(s.get("next_poll_after_seconds") or 5))

asyncio.run(main())

Notes

  • auto quality reserves the max price on Sume, so pin a quality if you want a predictable reservation.
  • Sume does not stream partial images today: stream: true returns 400 streaming_not_supported.
  • A client timeout does not cancel the job. Store the job id and fetch the result later.

Choosing a mode

Sume's image route accepts sync (the default on POST /v1/images), async, subscribe and webhook. subscribe is an alias of sync with the same bounded wait, and not a stream. For a prompt that may run two minutes, only async and webhook fit: the first returns immediately and you poll, the second also returns immediately and Sume calls you on a terminal event. Keep polling as a backup for webhooks, because the docs call the webhook a delivery optimization and not your only recovery path.

The arithmetic is simple. A 30 second wait covers a quarter of a 120 second run (30 / 120 = 0.25), so with sync you would expect to land in the 202 branch for a long prompt and have to write the polling code anyway. Writing it once, as async, removes a branch.

Sources

Related posts

More in Models

All Models posts

Written by Sume