Swap the Sume video model with an env var and a catalog check in Node
Read the model id from VIDEO_MODEL, confirm it appears in GET /v1/videos/models, and fall back to sume/auto when it does not. A Node 20 script of 21 lines.

Put the video model id in an environment variable, check it against GET /v1/videos/models at startup, and use sume/auto when the id is not listed. That lets you move to a newly launched model by changing one setting, and it keeps the service running if a model id disappears from the catalog. The script below does the whole thing in about twenty lines of Node.
OpenAI's deprecations page lists the Videos API and the Sora 2 model ids (sora-2, sora-2-pro and three dated snapshots) with a shutdown date of 2026-09-24 and no replacement listed (read 2026-10-08). A hard-coded model string is what turns that kind of notice into an outage. A setting plus a catalog check turns it into a config change.
The script
Save it as video.mjs and run SUME_API_KEY=... VIDEO_MODEL=wan-3.0 node video.mjs. Top-level await needs an ES module, which the .mjs extension gives you.
const base = "https://api.sume.com";
const headers = { Authorization: `Bearer ${process.env.SUME_API_KEY}` };
const wanted = process.env.VIDEO_MODEL ?? "seedance-2.5";
const res = await fetch(`${base}/v1/videos/models`, { headers });
if (!res.ok) throw new Error(`catalog ${res.status}`);
const { data } = await res.json();
const ids = new Set(data.map((m) => m.id));
const model = ids.has(wanted) ? wanted : "sume/auto";
if (model !== wanted) console.warn(`${wanted} not in catalog, using ${model}`);
const submit = await fetch(`${base}/v1/videos`, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
"Idempotency-Key": `promo-${model}-0042`,
},
body: JSON.stringify({ model, prompt: "Slow push-in on a ceramic mug", duration: 5 }),
});
console.log(submit.status, await submit.json());Why the fallback is sume/auto
Sume documents model: "sume/auto" as a way to let Sume select the model family. The poll response reports sume/auto, and Sume does not say which family ran. Resolution is a pure function of the normalized request and the catalog version, so an idempotent replay gets the same route and price.
The cost of that convenience is that you cannot pin behavior. If your pipeline depends on one family's look, fail loudly instead of falling back. Replace the console.warn with a throw in that case.
What the catalog tells you before you spend
Each entry in /v1/videos/models lists supported_resolutions, supported_aspect_ratios, supported_durations, supported_frame_images, supported_input_references, generate_audio, and pricing_skus. The duration limits differ by model, as the table shows.
| Model id | Documented duration |
|---|---|
| seedance-2.5 | 4 to 30 seconds |
| wan-3.0 | 2 to 30 seconds |
| minimax-h3 | 5 to 15 seconds |
| gemini-omni-flash-1.1 | 3 to 10 seconds |
Two details that bite
Check the live list for ids you have not used before. Sume's docs name the four above, but the catalog endpoint is the source of truth for what your key can call today.
- The
Idempotency-Keyin the script contains the model id. If the key stayed the same while the model changed, the body would differ and Sume would answer409 idempotency_conflict. /v1/videosdoes not acceptseed,size, or non-emptyprovider.options; each returns400 unsupported_parameter. Remove them from payloads you carry over from another vendor.
Rolling the change out
Change the variable in one environment first, submit a single five-second job, and read the result from the poll response before you change production. The submit returns a job id and a polling URL, and the job moves through pending, in_progress, and completed or failed. Video generation usually takes from 30 seconds to several minutes depending on the model and parameters, so poll about every 30 seconds, as the docs suggest.
If the check prints the fallback warning, treat it as a signal to look at the catalog, not as a success. A model that is missing from your key's catalog might be spelled differently, might not be enabled for the runtime you call, or might have been retired. Open GET /v1/videos/models in a terminal and look before you assume.
Sources
Related posts
More in Developers
- Swift: URLSession async/await for one 30-second Wan 3.0 job
A 28-line main.swift that submits wan-3.0 for 30 seconds, polls with Task.sleep and saves the MP4. Runs on macOS or Linux with swiftc.
- Switch video models by changing one string: what can still break
On Sume's /v1/videos you swap the model id and keep the body. Duration range, resolution and aspect ratio are the three fields that may need adjusting.
- sync, subscribe, async or webhook: which Sume mode for a video job
Sume's sync and subscribe modes wait at most 30 seconds, then return a job id. Use async or webhook for video; Python that survives a timed-out wait.
- Tall 1:3 strip on GPT Image 2.5: 1280x3840 passes, 1280x3856 fails
A tall scroll strip on Sume's GPT Image 2.5 can be 1:3 at most. 1280x3840 is exact and legal; one more row of 16 pixels breaks the 3:1 rule.
Written by Sume