A 4K image request returns 202: poll the job and fetch the result
POST /v1/images waits 30 seconds. Slow 4K or high-quality calls return 202 with a job envelope. Python that handles both and polls to completion.

POST /v1/images is synchronous by default: it waits up to 30 seconds and returns 200 with data[].url images. When generation is slower, Sume returns 202 and a job envelope instead of an error. The Sume docs name the slow cases: 4K, high quality and large n. They also say to examine the status code, not the body shape.
The two shapes
| Status | Body | Your next step |
|---|---|---|
| 200 | created, model, data[].url, usage.cost | Use the urls |
| 202 | data.job.id, status_url, result_url | Poll status, then fetch result |
| 502 | error envelope with code and next_action | Fix input or retry per retryable |
Python that handles both
Poll GET /v1/jobs/{id}/status until it reports terminal, then read GET /v1/jobs/{id}/result. The status endpoint's sume_status is completed on success, and the result endpoint answers 409 job_not_completed for any other state.
import os, time, requests
base = "https://api.sume.com"
headers = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
body = {"model": "google/nano-banana-2", "prompt": "Mountain at dawn",
"resolution": "4K", "aspect_ratio": "16:9"}
r = requests.post(base + "/v1/images", headers=headers, json=body, timeout=60)
if r.status_code == 200:
print([d["url"] for d in r.json()["data"]])
elif r.status_code == 202:
job_id = r.json()["data"]["job"]["id"]
while True:
s = requests.get(f"{base}/v1/jobs/{job_id}/status", headers=headers, timeout=30).json()["data"]
if s.get("terminal"):
break
time.sleep(s.get("next_poll_after_seconds") or 3)
if s.get("sume_status") == "completed":
print(requests.get(f"{base}/v1/jobs/{job_id}/result", headers=headers, timeout=30).json())
else:
print(r.status_code, r.text)
Alternatives
If you already know the call is slow, send mode: "async" and skip the wait. The job result keeps the platform's generic job shape for every product, so print it once to see where your images sit. Status and result bodies wrap their fields in data, which is why the loop reads ["data"].
How this was checked
Vendor facts come from the pages listed in the sources, read on 2026-10-05. Sume facts come from the Image API docs and the catalog code on main on the same date. Catalogs and limits change, so read the descriptors from GET /v1/images/models before you pin a number in production code.
Sources
Related posts
More in Developers
- Video job stuck in queued on Sume: limits by plan and queue_full
A queued video job is not a failure. Sume runs 1, 4, 8 or 20 jobs at once on Free, Pro, Startup and Scale, and queues the rest. 429 queue_full: queue full.
- Imagen 4 Fast has no 4:5: generate 3:4 and crop to 1080x1350 in Pillow
Imagen 4 Fast and Grok skip 4:5 on Sume. Request 3:4, then crop to 1080x1350 with ImageOps.fit and a top-biased centering so heads and product tops survive.
- Sume /v1/images 400 unsupported_parameter: check descriptors
Sume rejects an image parameter the model does not list. seed, output_compression, pixel size and stream also return 400 in v1. How to preflight it.
- Instagram 4:5 feed video from a 3:4 Sume render: the crop fractions
Sume models list 3:4 but not 4:5. Render 3:4, then crop 3.125% off the top and bottom with video-filter. Check the program free before the $0.02 encode.
Written by Sume