Image job progress bar: Sume has no percentage, so show job stages
ChatGPT Images 2.5 shows a progress percentage. Sume image jobs report queued, processing and completed plus events, and stream:true returns 400.

A user in OpenAI's Images 2.5 announcement thread notes that in instant mode there is now a progress percentage you can watch (OpenAI Developer Community, read 2026-10-04). People will ask your app for the same. On Sume that exact bar cannot be built, but an honest stage bar can.
What Sume reports
The Image API docs say Sume does not serve native streaming yet: every catalog row reports supports_streaming: false and stream: true returns 400 streaming_not_supported. The documented path is mode: "async", then GET /v1/jobs/:id/events for progress, or a webhook for the terminal event. The jobs docs list job statuses (queued, processing, completed, failed, canceled) and events such as job.created, job.queued, job.started, generation.submitted, job.completed and job.failed. None of these carries a percentage.
| Signal | Where | Fraction of work? |
|---|---|---|
| queued, processing, completed | GET /v1/jobs/{id}/status | No |
| job.started, generation.submitted | GET /v1/jobs/{id}/events | No |
| Terminal event | Webhook or poll | No |
Build the bar from stages
Map the stages to labelled steps: Accepted, Waiting for a slot, Generating, Done. Do not draw a smooth bar that implies a fraction you do not have. Slow settings (4K, high quality, large n) are the likeliest to move from a 200 to a 202 job envelope, so build the async branch first.
Submit async and poll
Use exponential backoff in production and stop on a terminal status, as the docs advise. Do not resubmit the paid request only because your own poll timed out.
import os
import time
import requests
h = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
body = {"model": "openai/gpt-image-2.5", "prompt": "a poster of a red kite", "mode": "async"}
r = requests.post("https://api.sume.com/v1/images", headers=h, json=body, timeout=30)
status_url = r.json()["data"]["status_url"]
for _ in range(40):
text = requests.get(status_url, headers=h, timeout=30).text
print(text[:200])
if any(s in text for s in ("completed", "failed", "canceled")):
break
time.sleep(3)
Sources
Related posts
More in Developers
- Image quality defaults differ: OpenAI auto, Sume high, Ideogram medium
Omit quality and the tier differs: OpenAI defaults GPT Image 2.5 to auto, Sume to high, Ideogram 4.5 to medium, Image 1.0 to low. Pin it before you budget.
- Index-Echo bilingual SRT from a Chinese video to Sume cues
Index-Echo S2TT turns Chinese speech into timed bilingual subtitles in 60-second windows. Convert its SRT into Sume caption cues and burn the English line.
- Syllable-controlled translation for voiceover that must fit
Translated speech often runs longer than the original. Index-Homura targets length-controlled translation. How to budget words against clip time before TTS.
- Index-Translate subtitles: translate cues, then burn them in
Bilibili's Index-Translate covers 150 languages with a free OpenAI-compatible API. Translate each cue, then burn the result with Sume video captions.
Written by Sume