Port a Bedrock image call to Sume /v1/images in Python
Moving from boto3 invoke_model for Nova Canvas or Titan to Sume's REST call: the request mapping, the response shape, the status codes, and the swap code.

A Bedrock image call posts a task-specific JSON body and reads images from the response. Sume's call is one flat JSON body with the same fields for every model. The mapping is mostly renaming, plus three behaviour changes.
| Bedrock concept | Sume field |
|---|---|
| Prompt text | prompt |
| numberOfImages | n, capped per model |
| Source image, base64 | input_references[].image_url.url, a public HTTPS URL |
| maskImage, base64 | mask_url, GPT Image 2.5 only |
| Width and height | aspect_ratio, resolution or image_size |
| cfgScale, seed | No field; unsupported parameters return 400 |
Three behaviour changes
- Results are URLs, in
data[].url, not base64 strings. - The call waits 30 seconds by default, then returns
202with a job envelope. Handle it. - Errors come back as an envelope with
category,retryableandnext_action, and failed jobs are not billed.
A wrapper with the same return type
Most Bedrock callers want bytes back. This wrapper returns bytes and raises on anything that is not a finished image, so your downstream code does not change.
import os, requests
def generate_bytes(prompt: str, source_url: str | None = None,
model: str = "google/nano-banana-2") -> bytes:
body = {"model": model, "prompt": prompt}
if source_url:
body["input_references"] = [
{"type": "image_url", "image_url": {"url": source_url}}]
r = requests.post("https://api.sume.com/v1/images", json=body, timeout=90,
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"})
if r.status_code != 200:
raise RuntimeError(f"{r.status_code}: {r.text[:200]}")
return requests.get(r.json()["data"][0]["url"], timeout=60).content
open("out.png", "wb").write(generate_bytes("A ceramic mug on a wooden table"))A 202 raises in this wrapper. Add the polling loop from the timeout post when you move to higher qualities or sizes.
Sources
Related posts
More in Developers
- BullMQ delayed job that polls an AI video job and reschedules itself
A BullMQ worker reads Sume's job status once, then adds the next poll with a delay from next_poll_after_seconds, so no worker slot is held while a clip renders.
- A calendar file for AI model shutdown dates: .ics from Python
Generate an .ics file with all-day events and 14-day reminders for the gpt-image-1 and gpt-image-1.5 shutdown dates, then import it into any calendar app.
- Cancel a queued transcription job: what the 409 means
POST /v1/jobs/{id}/cancel works only before work starts. After that it returns 409 job_generation_already_started and the job finishes and bills normally.
- Celery task for an AI video API: submit, poll, retry on Wan 3.0
Two Celery tasks for Sume's /v1/videos: one submits a Wan 3.0 job with an Idempotency-Key, one polls with self.retry(countdown) and stops on a terminal status.
Written by Sume