Duration dropdown from supported_durations: 27, 29 and 8 choices
Seedance 2.5 offers 27 lengths, Wan 3.0 29, Omni Flash 1.1 8. Map supported_durations to options in TypeScript, with the price of the longest option.

supported_durations on GET /v1/videos/models is the list your length picker should render: Seedance 2.5 gives 27 choices (4 to 30 s), Wan 3.0 gives 29 (2 to 30 s) and Gemini Omni Flash 1.1 gives 8 (3 to 10 s). Build the dropdown from that array and the 400 for an unsupported length never reaches a user.
Counts and the price of the longest option
The ranges below come from the docs model pages; confirm them against the live array, because the docs say to always read supported_durations from the endpoint. The last column is the cost of the top option, so the picker can show a price next to the longest clip.
| Model | Range | Options | Longest clip | Rate per second | Total |
|---|---|---|---|---|---|
| seedance-2.5 | 4 to 30 s | 27 | 30 s, 720p, 9:16 | $0.5778 | $17.334 |
| wan-3.0 | 2 to 30 s | 29 | 30 s, 720p | $0.125 | $3.75 |
| gemini-omni-flash-1.1 | 3 to 10 s | 8 | 10 s, 720p | $0.125 | $1.25 |
| minimax-h3 | 5 to 15 s | 11 | 15 s, 768p | $0.075 | $1.125 |
Map the array to options
Fetch the catalog once per page load, find the selected model and map its durations. Keep the value as a number, because the request field duration is an integer.
const res = await fetch("https://api.sume.com/v1/videos/models", {
headers: { Authorization: `Bearer ${process.env.SUME_API_KEY}` },
});
const { data } = await res.json();
const model = data.find((m: { id: string }) => m.id === "wan-3.0");
const options = model.supported_durations.map((s: number) => ({
value: s,
label: `${s} s`,
}));
console.log(options.length, options[0], options.at(-1));Gotchas
Re-render the dropdown when the model changes: switching from Wan 3.0 (2 to 30 s) to Omni Flash 1.1 (3 to 10 s) must reset a 20 s choice, not keep it. The OpenAPI schema only says duration is an integer of at least 1, so the per-model limit lives in the catalog, not in the request schema.
Do this in your backend or a build step if the key must stay private. Never ship SUME_API_KEY to a browser.
Sources
Related posts
More in Developers
- Timeline body from a cut list in TypeScript: starts and coverage
Turn a cut list of source ranges into Timeline slots: starts are running sums rounded to 3 decimals, and 3 ranges of 3.55, 4.68 and 3.36 s make 11.59 s.
- Build the pricing_skus key from the resolution string: 4K is uppercase
Omni Flash 1.1 rates sit at per-video-second-360p, -720p, -1080p and -4K. Build the key from a template, mind the 4K case, total 10 s from $0.375 to $3.75.
- Which Sume API routes work without a key? Six public routes
Six Sume routes need no API key, including GET /v1/catalog and GET /v1/health. What they return, how they are limited, and a Python preflight for CI.
- Can polling hit the Sume read limit? 24 Pro jobs at 2 s use 6%
Polling every accepted job every 2 seconds uses 3.75% to 7.5% of a Sume plan's read budget. The arithmetic for Free, Pro, Startup and Scale, with the caveats.
Written by Sume