Choose an image model in code from the Sume catalog's parameters
Filter GET /v1/images/models by what a request needs (references, ratio, transparency), then rank the matches by endpoint price. Python script for Sume.

To choose a Sume image model in code, read GET /v1/images/models, keep the rows whose supported_parameters cover what your request needs, then price the survivors with GET /v1/images/models/{id}/endpoints and take the cheapest. Sume rejects a parameter the model does not list with 400 unsupported_parameter, so the descriptors are the exact allowlist: if a key is present, the model accepts it.
This replaces a hand-kept table of which model supports masks, how many references it takes and which ratios it knows, a table that goes stale as new models arrive almost weekly.
What do the descriptors look like?
From the Sume Image API page, read 2026-10-04: each parameter is one of three typed descriptors.
| Type | Shape | Example |
|---|---|---|
enum | {type, values} | aspect_ratio with a list of ratios |
range | {type, min, max} | n from 1 to 4; input_references from 0 to 10 |
boolean | present means supported | prompt; on ChatGPT Image 2.5, parameters such as background |
What is the selection script?
The function below takes the requirements as plain data: a minimum reference count, a required ratio and a list of keys that must be present. It prices each match from the endpoint record, whose pricing lines carry cost_usd per billable unit. Pricing for token-billed models such as ChatGPT Image 2.5 depends on quality and size, so check the line you get before treating a single number as comparable.
import os, requests
API = "https://api.sume.com/v1/images/models"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
def fits(sp, refs, ratio, keys):
if sp.get("input_references", {"max": 0})["max"] < refs:
return False
if ratio and ratio not in sp.get("aspect_ratio", {}).get("values", []):
return False
return all(k in sp for k in keys)
def price(model_id):
r = requests.get(f"{API}/{model_id}/endpoints", headers=H, timeout=30)
r.raise_for_status()
lines = r.json()["endpoints"][0]["pricing"]
return min(l["cost_usd"] for l in lines)
def pick(refs=0, ratio=None, keys=()):
rows = requests.get(API, headers=H, timeout=30).json()["data"]
ok = [m["id"] for m in rows if fits(m["supported_parameters"], refs, ratio, keys)]
return sorted((price(i), i) for i in ok)
if __name__ == "__main__":
print(pick(refs=2, ratio="4:5", keys=("quality",))[:3])What can go wrong?
Do not assume every parameter you want has a descriptor. Transparent output, for example, is documented only for ChatGPT Image 2.5, with other models returning 400. Treat an empty result as a real answer: no catalog model fits, so relax a requirement or split the job.
Model-level and endpoint-level supported_parameters are identical on Sume today because each model has one sume endpoint, so reading the list is enough for capability and the endpoint call is only needed for price.
Should the chosen model be pinned?
Resolve once, log the id, then pin it in config. If you want Sume itself to choose, send model: "sume/auto"; it is not a catalog row, the response echoes sume/auto and the family that served it is not disclosed. For repeatable output and audits, a pinned id is the better default.
Sources
Related posts
More in Developers
- Claude batch custom_id is 64 characters: keep SKU keys valid
Anthropic batch custom_id allows 1 to 64 letters, digits, underscore and hyphen. How to sanitize SKUs, avoid collisions and carry the key into Sume input.
- Claude Code 2.1.285 lists WebSocket MCP servers; Sume uses HTTP
Claude Code 2.1.285 shows WebSocket MCP servers in claude mcp list. Sume's hosted MCP is a remote HTTP server, added with --transport http.
- MCP error text showed a Bearer token: rotate the Sume API key
Claude Code 2.1.286 masks credentials after Bearer or Basic in MCP errors. If an old log shows a Sume key, replace it and keep keys out of logs.
- Claude Code scope re-authenticate prompt vs unattended Sume runs
Claude Code 2.1.288 prompts to re-authenticate when a server asks for more OAuth scope. Unattended runs cannot answer it, so grant write up front.
Written by Sume