Deno: a 30-second Wan 3.0 video with fetch and top-level await
A short Deno script that submits a 30-second wan-3.0 job, polls to completion and writes clip.mp4, using only fetch and no npm packages.

Deno can run a full Wan 3.0 job with no dependencies: fetch for the three calls, top-level await for the flow, and Deno.writeFile for the MP4. The script below submits wan-3.0 for 30 seconds at 720p, polls every five seconds, and exits with an error if the job ends as anything but completed.
The reserve for that request is $3.75. The Video generation page documents the submit, the pending / in_progress / completed / failed / cancelled statuses and the content endpoint used here.
clip.ts
Run it with deno run --allow-env --allow-net --allow-write clip.ts. The three permission flags are all it needs.
const base = "https://api.sume.com/v1/videos";
const key = Deno.env.get("SUME_API_KEY");
if (!key) throw new Error("SUME_API_KEY is empty");
const auth = { Authorization: `Bearer ${key}` };
const res = await fetch(base, {
method: "POST",
headers: { ...auth, "Content-Type": "application/json", "Idempotency-Key": "wan-deno-001" },
body: JSON.stringify({
model: "wan-3.0", prompt: "A paper boat drifting down a rain gutter, macro lens",
duration: 30, resolution: "720p", aspect_ratio: "16:9",
}),
});
if (!res.ok) throw new Error(`submit failed: ${res.status} ${await res.text()}`);
const { id } = await res.json();
let status = "pending";
while (status === "pending" || status === "in_progress") {
await new Promise((r) => setTimeout(r, 5000));
status = (await (await fetch(`${base}/${id}`, { headers: auth })).json()).status;
}
if (status !== "completed") throw new Error(`job ended as ${status}`);
const mp4 = await fetch(`${base}/${id}/content?index=0`, { headers: auth });
await Deno.writeFile("clip.mp4", new Uint8Array(await mp4.arrayBuffer()));Why it is written this way
- The key is read from
SUME_API_KEYand the script throws if it is empty, so a missing variable never turns into an unauthenticated request. - The submit checks
res.okand prints the response body. A402 insufficient_creditsbody names the shortfall, which is the quickest way to learn the hold was larger than the balance. - The polling loop has no timeout on purpose; add one if the script lives inside a scheduled task with a hard wall-clock limit.
Cost by resolution
Change resolution and nothing else in the script:
| resolution | 30-second reserve |
|---|---|
| 480p | $1.875 |
| 720p | $3.75 |
| 1080p | $7.50 |
Smoke test before the 30-second run
Run the script once with "duration": 2 and "resolution": "480p" before you trust it. Wan 3.0 accepts 2 seconds, and that job reserves $0.125, against $3.75 for the full 720p clip. It proves the key, the polling and the file write for the price of a coffee-sized fraction of one real run.
Scaling to a list of prompts
For several prompts, wrap the submit in a function and keep a unique Idempotency-Key per prompt, such as the prompt's slug plus its resolution. Submit them in a small group and poll each id; the Sume plan limits decide how many can be accepted at once, so a 429 is a signal to wait and retry with the same key.
Sources
Related posts
More in Developers
- Deploy check: does your video model id and duration exist on Sume?
A Python preflight that reads GET /v1/videos/models and fails the deploy when VIDEO_MODEL is not a catalog id or the duration is outside supported_durations.
- detach_source_has_no_audio: check probe.has_audio first
Audio detach fails with detach_source_has_no_audio on silent video. Probe has_audio with a free frames-false video inspect first. Refusal codes listed.
- Docs page to explainer video: chunk the script under the TTS cap
Split a long document into voice-over chunks under Sume's 20,000-character TTS request limit and price them at $0.0475 per 1,000 characters. Runnable Python.
- Does Seedance audio cost extra on Sume? generate_audio and the price
Seedance prices on Sume are per video token and carry no separate audio line. What generate_audio does, what it defaults to, and the 10 s price either way.
Written by Sume