'frame_images is only accepted on auto': use the flat frame fields
Video Router refuses frame_images and input_references on a pinned model. Send image_url, end_image_url or reference_*_urls there, or move to POST /v1/videos.

The 400 "frame_images is only accepted on auto- / sume/auto / auto." means you sent the OpenRouter-style frame_images array to POST /v1/video-router/generate with a pinned model such as seedance-2.5. On that route, pinned models take flat fields: image_url for the first frame and end_image_url for the last. The same refusal exists for input_references and for task.
Two routes, two vocabularies
Sume has two ways to create a video job, and the docs recommend POST /v1/videos for new work. That route is shaped like the OpenRouter video API and accepts frame_images with a frame_type of first_frame or last_frame, plus input_references. The older Video Router keeps its flat vocabulary for pinned models and only lets auto-, sume/auto and auto use the array forms. Both create the same jobs with the same model ids, so moving a call is a path-and-body change.
| Intent | POST /v1/videos | POST /v1/video-router/generate (pinned model) |
|---|---|---|
| First frame | frame_images entry, frame_type first_frame | image_url (alias first_frame_url) |
| Last frame | frame_images entry, frame_type last_frame | end_image_url (alias last_frame_url) |
| Style or content reference image | input_references, type image_url | reference_image_urls |
| Reference video | input_references, type video_url | reference_video_urls |
| Reference audio | input_references, type audio_url | reference_audio_urls |
Convert the array in a few lines
If you already have an OpenRouter-style body, this converter produces the flat form for a pinned model. It only builds the dictionary and prints it, so it runs without a key and creates no job.
def to_flat(body: dict) -> dict:
flat = {k: v for k, v in body.items() if k not in ("frame_images", "input_references")}
for f in body.get("frame_images", []):
key = "image_url" if f["frame_type"] == "first_frame" else "end_image_url"
flat[key] = f["image_url"]["url"]
names = {"image_url": "reference_image_urls", "video_url": "reference_video_urls",
"audio_url": "reference_audio_urls"}
for ref in body.get("input_references", []):
flat.setdefault(names[ref["type"]], []).append(ref[ref["type"]]["url"])
return flat
print(to_flat({
"model": "seedance-2.5",
"prompt": "Slow push-in on a ceramic mug",
"frame_images": [{"type": "image_url", "frame_type": "first_frame",
"image_url": {"url": "https://example.com/a.png"}}],
}))
What the conversion cannot fix
Flat fields obey their own pairing rules. A frame and a reference list cannot travel together on the Video Router, and a last frame needs a first frame. Those are covered in the neighbouring posts on the "not both" and "requires image_url" errors. The /v1/videos route has a different rule when both arrays are present: frame_images controls the mode and the request runs as image-to-video, as the related post on which field wins explains.
When to stay on the Video Router
Keep the flat route if your integration already uses it and has no reason to change; the docs say it stays available and does not change. Pick /v1/videos when you want the OpenRouter-shaped wire or the Idempotency-Key replay behaviour described on the Sume differences table. Do not mix the two vocabularies inside one request: an unknown key on the Video Router is a validation error, not an ignored field. That strictness is useful: a typo in a field name fails fast instead of silently dropping your last frame and billing a clip that ignored it. Treat the 400 as the cheapest debugging tool in the pipeline.
Sources
Related posts
More in Developers
- frame_images beats input_references on Sume /v1/videos
If one /v1/videos request has both frame_images and input_references, Sume runs image-to-video and uses the frames. How to keep a style reference working.
- Free plan: 120 writes a minute but 6 accepted jobs, which hits first
Video batches on Sume hit queue_full long before the write rate limit. Per-plan arithmetic for 429 rate_limited versus queue_full, with a calculator.
- Gemini 2.5 Flash Image shut down Oct 2: check old IDs on Sume
Google shut down gemini-2.5-flash-image on October 2, 2026 and points to Lite. On Sume an unknown model id returns 404 model_not_found; use a catalog id.
- Gemini Omni 1.1 Flash has no shutdown date yet: how to pin and watch
Google lists gemini-omni-1.1-flash with no shutdown date announced, while Veo 3.1 previews end October 22. Pin the id, and watch the deprecations page.
Written by Sume