Fallback chain for a 30-second AI video: first catalog row that fits
Kling 4.0 is rolling out in stages. Pick the first Sume video id whose catalog row lists 30 seconds, and stop with an error if none does.

Kling's guide says feature availability may vary during the initial rollout of Kling 4.0, and fal says endpoint names and pricing come at launch. The safe pattern is a short chain: ask the Sume catalog which ids list 30 seconds, take the first one in your preference order, and stop with an error if none matches.
Why a fixed model id breaks
A hard-coded id fails in two ways in a launch week. The id you want is not in the catalog yet, so the call returns model_not_found (404). Or the id exists but its row does not list the length you ask for, and the call returns unsupported_capability (400). Both are cheap to avoid when you read the row first.
Sume validates each request against the row, so it never silently shortens a 30-second ask. That is good for billing, and it means your code has to do the choosing.
The chain
Order the ids by what you want. On Sume today, seedance-2.5 (4-30 s) and wan-3.0 (2-30 s) are the catalog ids that reach 30 seconds, and kling-3 stops at 15 seconds. Put a Kling 4.0 id first the day it appears.
import os, requests
BASE = "https://api.sume.com/v1/videos"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
WANT, PREFER = 30, ["seedance-2.5", "wan-3.0"]
rows = requests.get(BASE + "/models", headers=H, timeout=30).json()["data"]
fit = {m["id"] for m in rows if WANT in (m.get("supported_durations") or [])}
model = next((m for m in PREFER if m in fit), None)
if model is None:
raise SystemExit(f"no catalog row lists {WANT} s")
body = {"model": model, "duration": WANT, "resolution": "720p",
"prompt": "A slow dolly past a row of ceramic mugs on a shelf"}
r = requests.post(BASE, headers={**H, "Idempotency-Key": "fallback-30s-001"},
json=body, timeout=60)
print(model, r.status_code, r.json().get("polling_url"))What Sume's catalog says about 30 seconds
The table is the catalog's own view of the length and what each id accepts, which is the part that your chain should read at run time.
| Id | Duration | Resolutions | Notes |
|---|---|---|---|
| seedance-2.5 | 4-30 s | 480p, 720p, 1080p | t2v, i2v with start/end frame, r2v |
| wan-3.0 | 2-30 s | 480p, 720p, 1080p | t2v, i2v, r2v; audio |
| kling-3 | 4-15 s | 720p, 1080p | Stops at 15 s; no reference urls |
Rules for the chain
- Send an
Idempotency-Keyon the submit, so that a retry of the same body replays the same job. - Do not retry a 400 on a different id with the same key: a key that is reused with a different body returns 409.
- Log the id that served the job. Prices differ by id, so the bill follows the model you picked.
What the chain does not do
It does not make two models look the same. Seedance 2.5 and Wan 3.0 render a prompt differently, so a fallback is a different take, not a retry of the same take. If a client has approved a look on one id, do not swap the id behind their back; surface the swap in your own job record.
It also does not hide cost. Sume reserves the price of the id that you picked at submit and refunds it on failure, so the chain is cheap to run in a launch week: a failed pick before submit costs nothing. Compare the price of each candidate before you order them, and put the cheaper id first if the look is equal.
Sources
Related posts
More in Developers
- Fan out one Sume clip to three platforms: one webhook, three task keys
Receive one job.completed webhook per Sume job, then enqueue a task per platform. Key each task by job id plus platform so a retry never double-posts.
- Sume video content 409: job_not_completed vs job_failed in Python
A 409 from /v1/videos/{id}/content means two things. job_not_completed is retryable, job_failed is not. Here is a Python handler that tells them apart.
- Fields Omni rejects on Sume: generate_audio false, bitrate_mode
Which request fields Sume's gemini-omni-flash-1.1 refuses or lacks: generate_audio false, bitrate_mode, reference_audio_urls, plus edit-mode rules.
- Filter the Sume video catalog in Python for 1080p and audio references
Instead of guessing which video model takes what, read GET /v1/videos/models and filter it. This Python script lists models with 1080p and audio_url references.
Written by Sume