Sume image API size vs resolution vs aspect_ratio: which to send
On POST /v1/images, size is only a shorthand for a resolution tier and exact pixels are not served. Send resolution and aspect_ratio from the model's list.

On POST /v1/images, send aspect_ratio for the shape and resolution for the size tier, and treat size as nothing more than a shorthand for the resolution tier. The Image API page, read 2026-10-03, says size is a shorthand for a resolution tier and that explicit pixel sizes are not served in v1: output_compression, seed and explicit pixel size are in the schema but no model advertises them, so they return 400 unsupported_parameter.
That is different from the older Image 1.0 shape, which accepts an image_size with custom pixels on some models. If you are porting a request from there, the field you want on /v1/images is aspect_ratio plus, where the model lists it, resolution.
Which models list resolution
Only five catalog rows publish a resolution descriptor. Everything else has one fixed output tier, so sending resolution to it is a 400.
| Model | Allowed `resolution` values |
|---|---|
| Nano Banana 2 | 512, 1K, 2K, 4K |
| Nano Banana Pro | 512, 1K, 2K, 4K |
| Imagen 4 Ultra | 1K, 2K |
| Ideogram 4.5 | 1K, 2K |
| Soul | 720p, 1080p |
Shape comes from aspect_ratio
The normalized ratios are 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 4:5, 5:4, 1:2, 2:1, 1:4, 4:1, 1:8, 8:1, 9:21 and 21:9, with auto for the provider's choice, but each model accepts only the subset in its descriptor. Read supported_parameters before you pin one.
Pixel-exact targets such as 1080×1350 are a post-step, not a request field. The docs note that 4:5 is Instagram portrait (1080×1350), not 4:3, and that Nano Banana Pro takes aspect_ratio: "4:5" natively and an exact size is a documented post-step via job target_pixels. If you need exact pixels, generate at the nearest ratio and resize with Pillow.
A request that passes on a model with a tier
Nano Banana 2 lists 512, 1K, 2K and 4K and a wide ratio set. A tier plus ratio request looks like this. A call that is still running after the 30-second wait returns 202 with a job envelope instead of 200, so check the status code before reading data; see Jobs and results.
import os
import requests
resp = requests.post(
"https://api.sume.com/v1/images",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
json={
"model": "google/nano-banana-2",
"prompt": "studio photo of a red ceramic mug",
"resolution": "2K",
"aspect_ratio": "4:5",
},
timeout=60,
)
resp.raise_for_status()
if resp.status_code == 202:
print("still running:", resp.json()["data"]["status_url"])
else:
for image in resp.json()["data"]:
print(image["url"])What a wrong field costs
A rejected request does not generate, so it is not billed. The fix is to read GET /v1/images/models first and send only parameters in the model's supported_parameters; the same call tells you whether the model lists resolution at all.
Sources
Related posts
More in Developers
- Music 1.0 is retiring: switch to /v1/music-router/generate in one line
Sume's Music 1.0 routes keep working but now resolve through the Music Router. Which URL to change, what stays the same, and how to see which engine ran.
- Retry Sume 429s in TypeScript: a fetch wrapper that obeys retry-after
A small fetch wrapper for the Sume API: retry 429 only when the request is a GET or carries an Idempotency-Key, wait retry-after, and never loop on queue_full.
- Sume reserve, capture, refund: what your cost ledger should mirror
Sume reserves the estimate at submit, captures it on success and releases it on failure or cancel. Mirror the three states or cost reports will double count.
- Sume SDK 429 retry-after is capped at 60 seconds: what follows
createSumeClient waits at most 60 seconds per retry, with 20 percent jitter and 2 retries by default. What that means for a long retry-after and a fix.
Written by Sume