By default the router tries our listings in routing order and fails over before the first byte — never mid-answer. Uptime is our own measurement; an hour stays grey until it has a sample. Open the row for the provider's specs and policies.
curl https://api.routerplus.com/v1/videos \
-H "Authorization: Bearer $TM_API_KEY" -H "content-type: application/json" \
-d '{"model":"hailuo-3-max","prompt":"a lighthouse at dusk","seconds":"5"}'
# then GET /v1/videos/{id} until "completed", and GET /v1/videos/{id}/content for the MP4# OpenAI SDK — only the base URL changes. A video is a job: create it, then poll. import os, time from openai import OpenAI client = OpenAI(base_url="https://api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"]) video = client.videos.create(model="hailuo-3-max", prompt="a lighthouse at dusk", seconds="5") while video.status in ("queued", "in_progress"): time.sleep(5); video = client.videos.retrieve(video.id) client.videos.download_content(video.id).write_to_file("video.mp4")
import { writeFileSync } from "node:fs"; import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.routerplus.com/v1", apiKey: process.env.TM_API_KEY }); let video = await client.videos.create({ model: "hailuo-3-max", prompt: "a lighthouse at dusk", seconds: "5" }); while (video.status === "queued" || video.status === "in_progress") { await new Promise((r) => setTimeout(r, 5000)); video = await client.videos.retrieve(video.id); } const file = await client.videos.downloadContent(video.id); writeFileSync("video.mp4", Buffer.from(await file.arrayBuffer()));
| output video | $0.05 / second · 480p |
| output video | $0.08 / second · 768p |
Every billed response carries usage.cost — recompute your bill from the wire.
Values outside these are refused with a 400 that names the field.
An hour counts at the best provider's uptime: a request goes to another provider when one fails. Grey hours have no sample yet.