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
- Sume job status: stop on terminal, fetch on result_ready
A Sume status reply has two booleans. terminal says stop polling; result_ready says GET /result will work. Failed and canceled jobs stop but have no result.
- 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.
- Sume ratelimit-limit differs on reads and writes: read the header
ratelimit-limit shows the budget the current call spent from, so a GET shows reads and a POST shows writes. Read the header; do not hard-code the plan table.
- 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.
Written by Sume