Does this video model take a last frame? Check /v1/videos/models first

Read supported_frame_images from GET /v1/videos/models before sending a first or last frame to Sume. A small Python guard that fails before any spend.

4 min readSume
All posts

How do I know if a Sume video model accepts a last frame?

Read its entry in GET /v1/videos/models and look at supported_frame_images. A model that takes both ends lists first_frame and last_frame. One that lists only first_frame is image-to-video from an opening still. An empty list means the model takes no frame images at all.

This matters now that first-and-last-frame control is a headline feature. Google's Gemini Omni 1.1 Flash post lists first and last frame control, but other catalog models differ. A request with a capability the model lacks fails with 400 unsupported_capability, and it is cheaper to catch that before the call.

The list is a contract, not a hint. If a model reports first_frame only, do not send a last_frame and hope: the request is refused, and nothing is generated. Reading the descriptor is a free GET, so it costs less than one failed submit and tells you the allowed durations and resolutions at the same time.

Descriptor fields worth reading

Video model descriptor fields on GET /v1/videos/models (docs.sume.com, read 2026-10-06)
FieldTells youUse it to
supported_frame_imagesfirst_frame, last_frame, or bothGate a pinned opening or ending
supported_input_referencesimage_url, video_url, audio_urlGate reference inputs by type
supported_durationsAllowed secondsClamp duration before submit
supported_resolutions480p, 720p and so onPick a resolution that exists
generate_audioWhether audio can be toggledAvoid sending a rejected flag

A guard that runs before you spend

The pure function takes the parsed data list, so you can unit test it with a fixture. fetch_models is the only part that touches the network and needs your key.

import json, os, urllib.request

def frame_support(models: list, model_id: str) -> list:
    for m in models:
        if m["id"] == model_id:
            return m.get("supported_frame_images") or []
    raise KeyError(f"unknown model {model_id}")

def can_pin(models, model_id, first=True, last=False) -> bool:
    have = frame_support(models, model_id)
    return (not first or "first_frame" in have) and (not last or "last_frame" in have)

def fetch_models() -> list:
    req = urllib.request.Request(
        "https://api.sume.com/v1/videos/models",
        headers={"x-api-key": os.environ["SUME_API_KEY"]},
    )
    with urllib.request.urlopen(req, timeout=15) as r:
        return json.load(r)["data"]

demo = [{"id": "a", "supported_frame_images": ["first_frame", "last_frame"]},
        {"id": "b", "supported_frame_images": ["first_frame"]}]
print(can_pin(demo, "a", last=True), can_pin(demo, "b", last=True))

Sending the frames

Each frame goes in frame_images as {type: "image_url", image_url: {url}, frame_type: "first_frame" | "last_frame"}. If you also send input_references, the frame images win and the request is image-to-video, so use one field or the other. Keep every URL public HTTPS.

Call fetch_models once at startup, cache the list, and refresh it on deploy. The catalog is the source of truth for what each model accepts, and the cached copy keeps a hot path from adding a request to every submit.

A last frame is also a creative commitment. The model has to travel from the first still to the last one inside the clip length you chose, so pick two frames that a plausible camera move or action can connect, and give the prompt the verb that links them. Two unrelated stills tend to produce a cut or a morph rather than a shot, whichever model you use.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume