Check durations, frames and references against the Sume video catalog

Read supported_durations, supported_resolutions, supported_frame_images and supported_input_references from /v1/videos/models and refuse bad requests early.

4 min readSume
All posts

You can catch most Sume video 400s in your own code by reading four fields per model from GET /v1/videos/models: supported_durations, supported_resolutions, supported_frame_images and supported_input_references. The script below checks a request against them and lists the problems. It does not create a job, and a valid result is not a guarantee, because some limits live only in the validation code.

What the catalog entry tells you

Each entry in data carries the fields in the table. They are the public contract of the OpenRouter-shaped route, and the Video Router uses the same ids and ranges.

Catalog fields to preflight on GET /v1/videos/models, from the Sume docs on main (read 2026-10-05)
FieldUse it to check
supported_durationsThe whole-second values you may send
supported_resolutions480p, 720p, 768p, 1080p and so on, per model
supported_aspect_ratios16:9, 9:16 and the rest
supported_frame_imagesfirst_frame and last_frame allowed
supported_input_referencesimage_url, video_url, audio_url allowed
generate_audioWhether the model can produce audio

The script

It takes a model id and a description of the request, then prints each mismatch. Run it before you submit anything; it needs only your key in the environment and never prints it.

import os
import requests

hdr = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
r = requests.get("https://api.sume.com/v1/videos/models", headers=hdr, timeout=30)
r.raise_for_status()
cat = {m["id"]: m for m in r.json()["data"]}

def check(model, seconds, res, ratio, frames=(), refs=()):
    m = cat.get(model)
    if not m:
        return ["unknown model id"]
    bad = []
    if seconds not in (m["supported_durations"] or []):
        bad.append(f"duration {seconds} not in {m['supported_durations']}")
    if res not in (m["supported_resolutions"] or []):
        bad.append(f"resolution {res} not offered")
    if ratio not in (m["supported_aspect_ratios"] or []):
        bad.append(f"aspect {ratio} not offered")
    bad += [f"frame {f} unsupported" for f in frames if f not in (m["supported_frame_images"] or [])]
    bad += [f"reference {x} unsupported" for x in refs if x not in (m["supported_input_references"] or [])]
    return bad

print(check("seedance-2.5", 12, "1080p", "9:16", ["last_frame"], ["audio_url"]))

What the preflight does not see

The catalog gives ranges and types. It does not give counts of references, clip lengths of reference files, pairing rules or the model-specific messages. Examples are 9 images, 3 videos and 3 audios on most models, a 15 second total on Wan's reference videos, a last frame needing a first frame, or Gemini Omni's three-second reference clips. Those are enforced by the validation on the create call, so treat them as a second layer and keep the related posts on each error close.

Where to run it

Put the check in the code path that builds the request, not in a separate tool. Cache the catalog for a short time to avoid a call per request, and refresh when you see an unexpected 400. If a model is gated by provider configuration, it can be absent from your list, which the check reports as an unknown id instead of a pricing or routing problem.

For tests, keep a small table of known good and known bad requests per model, run them through the check on every deploy, and compare the result with a live call once in a while. Drift between the catalog and your assumptions is the usual cause of surprise 400s: a model gains a longer range, or a new reference type appears, and your hard-coded limits are suddenly wrong in either direction.

Finally, make the output actionable. A list of problems is useful, but a corrected request is better. Where the fix is mechanical, such as clamping a duration to the nearest supported value, apply it and log the change; where it changes the creative intent, such as dropping a last frame, stop and ask.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume