Nano Banana 2.1 on Sume in Python: handle the 200 and 202 replies

Call google/nano-banana-2.1 on Sume's /v1/images in Python and handle both the 200 image reply and the 202 job envelope, with polling to the result URL.

4 min readSume
All posts

POST /v1/images waits up to 30 seconds. If the image finishes it returns 200 with data[].url. If it does not, Sume returns 202 with a job envelope, and you poll status_url until terminal is true, then read result_url. The function below handles both and checks the status code rather than guessing from the body, as the Sume Image API docs advise.

The code

It needs requests and a SUME_API_KEY environment variable. The model id is google/nano-banana-2.1. 2K and 16:9 are examples; read the model's supported_parameters first.

import os
import time
import requests

BASE = "https://api.sume.com"
HEADERS = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}

def generate(prompt):
    body = {"model": "google/nano-banana-2.1", "prompt": prompt,
            "resolution": "2K", "aspect_ratio": "16:9"}
    r = requests.post(f"{BASE}/v1/images", headers=HEADERS, json=body, timeout=60)
    r.raise_for_status()
    if r.status_code == 200:  # finished inside the 30 s budget
        return [item["url"] for item in r.json()["data"]]
    envelope = r.json()["data"]  # 202: a job, not an image body
    while True:
        s = requests.get(envelope["status_url"], headers=HEADERS, timeout=30)
        s.raise_for_status()
        status = s.json()["data"]
        if status["terminal"]:
            break
        time.sleep(status.get("next_poll_after_seconds") or 2)
    if status["sume_status"] != "completed":
        raise RuntimeError(f"job ended as {status['sume_status']}")
    res = requests.get(envelope["result_url"], headers=HEADERS, timeout=30)
    return [a["url"] for a in res.json()["data"]["result"]["artifacts"]]

if __name__ == "__main__":
    print(generate("matte black bottle on marble, soft window light"))

What each reply looks like

The two replies have different shapes, so a single parser for both will fail.

Sume POST /v1/images replies, Image API and jobs docs (read 2026-10-07)
StatusBodyWhat to read
200created, model, data (a list), usagedata[].url and usage.cost
202data.job, data.status_url, data.result_urlPoll status_url, then result_url
Job resultdata.result.artifactsartifacts[].url, a Sume-hosted URL

Notes that matter

  • Do not resubmit on a timeout. A client timeout does not cancel the job, which keeps running and bills.
  • Slow settings such as 4K, high quality or a large n are the likeliest to return 202.
  • usage.cost is the billed USD amount on a 200. Token counts there are always 0.
  • Failed and cancelled generations are not charged, per the Image API docs.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume