Build an AI image progress UI: gate on supports_streaming false

Sume's image catalog reports supports_streaming false on every row. Build the progress UI from job states and gate a live preview on that field.

5 min readSume
All posts

To build an AI image progress UI on Sume, read supports_streaming from GET /v1/images/models and show a live preview only when it is true. Today the field is false on every row, and a request with stream returns 400 streaming_not_supported, so build the UI from job states: queued, processing, then completed or failed.

Why gate on the field

The OpenAI guide describes streaming partial images for its own API. Sume does not pass that through: the docs say real streaming would need partial-image events in the job pipeline, and the catalog says so with supports_streaming: false. If your UI reads the field, it will pick up streaming the day a model turns it on, with no code change. If it hard-codes the answer, you ship a dead code path or a broken request.

Do not fake percent. The status poll has no progress number, so a bar that reaches 90 percent on a timer misleads people. Show the state and the elapsed time.

Progress signals available on Sume images (read 2026-10-05)
SignalAvailableUse
supports_streamingfalse on every rowGate any live preview
stream request field400 streaming_not_supportedDo not send
status valuesqueued, processing, completed, failed, canceledState chip
next_poll_after_secondsIn the poll responsePolling interval
events_urlPull snapshot, not SSEOptional history

Read the gate

Fetch the catalog once per session and read the row for the model you use.

import os, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}

r = requests.get("https://api.sume.com/v1/images/models", headers=H, timeout=30)
r.raise_for_status()
rows = {m["id"]: m for m in r.json()["data"]}
m = rows.get("openai/gpt-image-2.5")
if m is None:
    raise SystemExit("model not in catalog")
if m.get("supports_streaming"):
    print("show a live preview")
else:
    print("show queued -> processing -> done states")

What to show instead

These four elements give a calm interface without any claim about progress that the API cannot support.

  • A state chip that follows queued, processing and completed.
  • Elapsed seconds, so a long 4K job looks alive.
  • A cancel button wired to the job, since a client timeout does not cancel it.
  • A placeholder with the final aspect ratio, so the layout does not jump when the image arrives.

Handle the three endings

A job ends in one of three ways, and the interface should treat each one clearly. On completed, fetch the result and swap the placeholder for the image. On failed, show the public error message from the status response and offer a retry, and tell the user that failed jobs are not billed. On canceled, return to the form with the prompt kept, so nothing typed is lost.

Keep the polling interval from the server. The response carries next_poll_after_seconds, and following it keeps the request volume low for you and for the API. When the tab goes to the background, slow the loop or pause it, and run one status read on focus so the page is current again the moment someone returns.

Finally, store the job id in the page state or the URL. A reload then resumes the same job instead of paying for another.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume