MiniMax H3 Max in TypeScript: submit, poll and download with fetch
A TypeScript script under 30 lines: submit a minimax-h3-max job on Sume, poll until completed, save the MP4. Status values and the 409 on failed jobs.

MiniMax H3 Max, id minimax-h3-max, takes 5 to 15 seconds at 480p, 768p or 1080p, with the 1080p tier a latent refinement of native 768p. On Sume it is an asynchronous job: submit returns a 202 with a polling URL, you poll until the status is completed, and then you download the file. This post is the whole loop in TypeScript, using only the built-in fetch in Node 18 or later.
What does the script look like?
Set SUME_API_KEY in the environment. The script submits a 5-second 768p job, polls every five seconds, and writes h3max.mp4. It checks the status and stops on failed instead of requesting content.
import { writeFileSync } from "node:fs";
const base = "https://api.sume.com/v1/videos";
const headers = {
Authorization: `Bearer ${process.env.SUME_API_KEY}`,
"Content-Type": "application/json",
};
async function main() {
const body = JSON.stringify({
model: "minimax-h3-max",
prompt: "A paper boat drifting down a rainy street at dusk",
duration: 5,
resolution: "768p",
});
const res = await fetch(base, { method: "POST", headers, body });
const { id } = await res.json();
for (;;) {
const r = await fetch(`${base}/${id}`, { headers });
const job = await r.json();
if (job.status === "failed") throw new Error("job failed");
if (job.status === "completed") break;
await new Promise((ok) => setTimeout(ok, 5000));
}
const file = await fetch(`${base}/${id}/content?index=0`, { headers });
writeFileSync("h3max.mp4", Buffer.from(await file.arrayBuffer()));
}
main();What do the statuses mean?
The poll response uses OpenRouter's names: pending for a queued job, in_progress for one that is processing, then completed or failed. The finished object lists unsigned_urls, and the usage.cost field is the Sume billable amount. A content request on a failed job is a 409 job_failed, which is why the loop stops first.
What would a real client add?
A timeout on the loop, a check of res.ok on the submit so a 402 insufficient_credits or a 400 is shown with its body, and an Idempotency-Key header on the submit so a retry returns the original job instead of billing a second. At 768p a 5-second H3 Max clip is $0.50 billable, so a retry bug is cheap, but at 1080p it is $1.00 and it adds up.
Sources
Related posts
More in Developers
- Mistral Vibe tool globs: keep Sume to read-only tools
Vibe prefixes MCP tools with the server name and lets you allow or deny them by glob. A read-only Sume allowlist for a key that otherwise sees paid tools.
- Mix Seedance, Kling and Omni clips in one video: shared aspect ratio
16:9 and 9:16 are the aspect ratios Seedance 2.5, Kling 3 and Gemini Omni Flash 1.1 all list. Set the Timeline output to match and plan before render.
- Mixed-language script: one Sume TTS request per language, then concat
A script that switches language mid-way needs one TTS request per language on Sume. Join up to 20 parts with timeline audio at $0.01.
- Gaps between joined MP3 clips: priming padding and Sume's wav default
Joined MP3 clips can leave tiny gaps because each file carries priming padding. Sume Timeline audio defaults to sample-exact wav. When to use mp3.
Written by Sume