Validate an image request against supported_parameters first
Sume rejects a parameter a model does not list with 400 unsupported_parameter. Read the catalog descriptors and check a request body before you POST /v1/images.

To avoid a 400 from POST /v1/images, read GET /v1/images/models and check your request body against the model's supported_parameters before you send it. The catalog is the parameter allowlist: if the selected model does not list a parameter, Sume rejects it with 400 unsupported_parameter instead of silently dropping it. Each descriptor is one of three shapes (boolean, enum with values, or range with min and max), so a short function can check a body locally.
What do the descriptors look like?
Each row in the catalog carries a supported_parameters object. The Image API page documents prompt as a boolean, aspect_ratio as an enum with a values list, n as a range with min and max, input_references as a range, and output_format as an enum. Descriptors are only present when the model has that capability: resolution and quality are left out when a model has none.
The per-model endpoints call, GET /v1/images/models/{id}/endpoints, returns the definitive set for that model plus pricing lines. Sume publishes a single endpoint per model.
Model ids are the org/slug form from the catalog, such as bytedance-seed/seedream-4.5. Legacy bare ids still work as aliases on the generate route, but the catalog lists the canonical ids, so look up by canonical id in the check.
| Type | Fields shown in the docs | Check to run |
|---|---|---|
| boolean | prompt | Key must exist in the descriptor |
| enum | aspect_ratio, output_format, resolution, quality | Value must be in values |
| range | n, input_references | Value must be between min and max |
What does a pre-flight check look like?
The function below fetches the catalog, finds the model, and reports each key that is missing or out of bounds. It skips model and provider, which are not model capabilities. Set SUME_API_KEY first.
import json, os, urllib.request
def get(path):
req = urllib.request.Request(
"https://api.sume.com" + path,
headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"]},
)
with urllib.request.urlopen(req) as r:
return json.load(r)
def problems(model, body):
rows = {m["id"]: m for m in get("/v1/images/models")["data"]}
if model not in rows:
return ["model not in catalog"]
sp = rows[model]["supported_parameters"]
out = []
for key, val in body.items():
d = sp.get(key)
if key in ("model", "provider") or d is None and key == "prompt":
continue
if d is None:
out.append(key + ": not listed")
elif d["type"] == "enum" and val not in d["values"]:
out.append(key + ": " + str(val) + " not in values")
elif d["type"] == "range" and not d["min"] <= val <= d["max"]:
out.append(key + ": outside " + str(d["min"]) + "-" + str(d["max"]))
return out
print(problems("bytedance-seed/seedream-4.5", {"prompt": "a mug", "n": 6}))Why check locally at all?
The catalog differs per model. The Image API page says GPT image models accept background and mask_url while other rows do not, and Ideogram 4.5 uses quality low, medium or high. A batch script that switches models mid-run will hit different allowlists, so a check by descriptor catches the mismatch before a request is spent.
Two parameters in the request schema, seed and output_compression, are accepted by the schema but no model advertises them in v1, so they return 400 unsupported_parameter at runtime. The check above flags them as not listed.
A practical pattern is to run the check in your job queue before you enqueue work, so a bad row fails in seconds with a readable message rather than as a 400 in the middle of a 200-image run. Log the model id and the list of problems together; when a descriptor changes after a catalog update, that log shows exactly which stored preset needs editing.
What should you do when the check fails?
Drop the key, pick a model whose descriptor lists it, or change the value to one in the enum. Cache the catalog for the length of a batch rather than fetching it per request, and refetch if you see a model_not_found.
Sources
Related posts
More in Developers
- Which MCP server lets Claude Code or Cursor generate video and images?
MCP servers that let Claude Code and Cursor make video and images: Sume, fal, Replicate, Runway, Higgsfield. Endpoints, sign-in, billing, setup.
- Idempotency keys for AI video APIs: retry without paying twice
An idempotency key makes a retried create return the original run or job instead of a second paid one. How Sume's Idempotency-Key works on each API.
- Signed webhooks for Sume video runs: events, retries, verification
Sume sends one HMAC-SHA256 signed POST when a Format, Action, or Agent Completion run completes or fails. Verify the raw body and dedupe on request_id.
- Spend caps for unattended AI agents: how Sume bounds each run
An unattended agent has no one to approve spend, so Sume caps generation per run: required on Agent Completions, and up to $500 on Format runs.
Written by Sume