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.

5 min readSume
All posts

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.

Descriptor types in supported_parameters, read 2026-10-04
TypeShapeExample
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
booleanpresent means supportedprompt; 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

All Developers posts

Written by Sume