GPT Image 2.5 custom size: the pixel rules and the 1024x1536 call
GPT Image 2.5 on Sume takes custom pixels via image_size: multiples of 16, edge up to 3840, aspect up to 3:1. Check your size, then call it with Python.

Yes, 1024x1536 works: both edges are multiples of 16, the longest edge is under 3840, the ratio is 3:2, and 1,572,864 pixels sits inside the allowed range. Send it as image_size: {"width": 1024, "height": 1536} on openai/gpt-image-2.5. Do not put it on size, which rejects WxH values.
OpenAI's own guide (read 2026-10-06) lists custom-size rules too. Sume's docs state the same shape of constraints for the GPT rows, and Sume validates before it submits.
The rules, as Sume states them
| Rule | Limit | 1024x1536 |
|---|---|---|
| Each edge | Multiple of 16 | Yes (64 x 16 and 96 x 16) |
| Longest edge | 3840 at most | 1536 |
| Aspect ratio | 3:1 at most | 1.5:1 |
| Total pixels | 655,360 to 8,294,400 | 1,572,864 |
Call it and check the file
The script asks for an opaque background and opens the result with Pillow to confirm the size that came back.
import io, os, requests
from PIL import Image
key = os.environ.get("SUME_API_KEY")
if not key:
raise SystemExit("set SUME_API_KEY")
r = requests.post(
"https://api.sume.com/v1/images",
headers={"Authorization": f"Bearer {key}"},
json={"model": "openai/gpt-image-2.5", "quality": "medium",
"image_size": {"width": 1024, "height": 1536},
"background": "opaque",
"prompt": "Tall product poster, matte bottle on a pale shelf"},
timeout=90,
)
print(r.status_code)
if r.status_code == 200:
img = requests.get(r.json()["data"][0]["url"], timeout=60)
im = Image.open(io.BytesIO(img.content))
print(im.size, im.mode)If it fails
- A
400names the field that broke a rule. A 1000x1500 request fails because 1000 is not a multiple of 16. - A
202means it took longer than 30 seconds. Poll thestatus_urland fetch the result. - Larger sizes cost more and are more likely to take the
202path.
Quality is a separate choice
Size and quality are different dials. If you omit quality on this row, the default is high, and auto reserves max. The cost guard post in this series covers that, so set quality on purpose when you set size.
Choosing a size on purpose
Pick the size from where the image will live, not from the largest number allowed. A tall poster, a wide banner and a square tile are three different requests, and each should use the smallest size that still looks sharp where it is shown.
The 3:1 limit matters for banners. A 3000x1000 request is exactly 3:1, but neither edge is a multiple of 16, so it fails; 3008x1008 passes, with a ratio just under 3:1. Round each edge to the nearest multiple of 16 before you send it, and let your code do that so a typo never reaches the API.
Sources
Related posts
More in Developers
- GPT Image 2.5 mask_url on Sume: build the PNG mask with Pillow
mask_url works only on the GPT Image 2.5 rows and must be a public HTTPS link. OpenAI wants an alpha channel and a matching size. A Pillow script builds one.
- Heroku H12 at 30 seconds: call Sume async, not sync
Heroku's router ends a request at 30 s (H12). Sume sync mode waits up to 30 s too. Submit async, return 202 to the browser, then poll or take a webhook.
- How long can an AI video Format run take? 90-minute limit
A Sume Format run expires 90 minutes after creation, sooner if silent. How to poll with backoff, when to use a webhook, and what expired means.
- How many 30-second videos can a Sume Pro key run at once? Wave math
Pro runs 4 generations at once and queues 20 more, so 24 accepted jobs. Use the plan table and a Python function to plan a 50-clip batch in waves.
Written by Sume