由 0G Foundation 提供
MiniMax-H3 (Hailuo-03) text-to-video and image-to-video, billed per generated second. `seconds` must be 4-15, and outside that range it is silently clamped rather than rejected. `size` names a resolution TIER, not output dimensions: send one of the names listed under Resolution Tiers. OpenAI pixel dimensions (1280x720) are also accepted, but they set only the aspect ratio and only for text-to-video — on image-to-video the ratio follows your reference image, so pixel dimensions have no effect there, while a tier name still selects the tier. Prompt required, up to 7000 characters. Image-to-video takes one first-frame image via multipart `input_reference`. Async: POST /v1/videos, poll GET /v1/videos/{id} until completed, then GET /v1/videos/{id}/content for the MP4.
$0.195
每生成秒
2K
計費分級 — 不是您傳送的大小
非同步 API — 影片生成使用非同步流程:提交任務、輪詢直到完成,再從單獨的端點下載檔案。生成需要數分鐘,因此請每 3-5 秒輪詢一次。以下範例展示三個步驟。
# 1. Submit the job. model, prompt and seconds are required; size is not.
# Omitting size is the recommended default — the model's own tier and aspect ratio apply. Each account may
# hold only a small number of unfinished jobs at once — 5 by default, set per deployment — and one over
# that returns 429 video_jobs_in_flight_limit.
#
# Some models clamp "seconds" INTO their supported range in BOTH directions rather than rejecting it,
# silently: below the minimum you get and pay for the minimum, above the maximum you get the maximum, and
# neither errors. That is the model's own behaviour, not something the router enforces, so check the model
# description for the range and for whether it clamps. You are billed for the clip actually produced, so
# where clamping happens a value outside the range costs something other than what you asked for. Not
# unlimited forgiveness: on a model whose price table is keyed on DURATION (variants carrying a
# duration_seconds dimension), a duration with no row is rejected up front with 400, listing the ones it
# does have. A model priced per second at a flat or resolution-only rate has a price for every duration, so
# that 400 cannot occur there.
#
# "size" names a resolution TIER, not output dimensions, and the two spellings are not equivalent. Pixel
# dimensions ("1280x720", OpenAI's spelling and what an SDK sends) select the ASPECT RATIO only, and only
# for text-to-video: on a 2K-only model they return a 2560x1440 clip billed at the 2K rate, not a 720p one.
# A tier name ("2K") addresses the tier directly — send only names that appear in
# pricing.variants[].dimensions.resolution, listed on this page under Resolution Tiers. On image-to-video
# the aspect ratio follows your reference image, so pixel dimensions have no effect there; a tier name
# still selects the tier.
curl "https://router-api.0g.ai/v1/videos" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-d '{
"model": "minimax-h3",
"prompt": "A cat surfing a wave at sunset",
"seconds": 6
}'
# Image-to-video is this same request with ONE more field — not a different flow, and not a different
# transport. Add "input_reference" to the body above; steps 2 and 3 are unchanged. It takes any of
# {"image_url": "https://…/first_frame.jpg"} for a reachable URL, {"image_url": "data:image/jpeg;base64,…"}
# for a local frame, or {"file_id": "…"}. An SDK sending a local file uses multipart instead, which the
# broker converts to that same data: URI — so the transport is a detail, the field is the interface.
# Prefer a URL for a large frame: base64 inflates the body by about a third, and the whole request must be
# 24 MB or less — over that it is 413 payload_too_large, tighter than the model vendor's own limit, so an
# image prepared against the vendor's docs can still be refused. One still frame only: last frame and
# reference image/video/audio are not exposed.
# Response: {"id": "v0_426354818031858", "status": "queued", "provider_address": "0x..."}
# 2. Poll until status is "completed". Generation takes minutes — 3-5s is a sane interval. The poll answers
# 200 and reports the job's own status, so a failure arrives as 200 + {"status":"failed"}, NOT as an error
# code. The SUBMIT response echoes what you sent; the POLL response reports what was actually rendered — so
# reconcile against the poll. Which fields carry that answer depends on the upstream:
# usage.output_video_duration when the provider reported a duration, size/seconds on some providers and not
# others. Read what is present rather than assuming a particular field.
curl "https://router-api.0g.ai/v1/videos/<VIDEO_ID>" \
-H "Authorization: Bearer <YOUR_API_KEY>"
# 3. Download the finished file. This is where 409 / 424 / 429 live: 409 = not ready yet, 429 = too many
# concurrent downloads (both retryable), 424 = the job failed and has no output (terminal).
curl "https://router-api.0g.ai/v1/videos/<VIDEO_ID>/content" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-o video.mp4
供應商路由
使用 X-0G-Provider-* 請求標頭,控制哪個供應商處理您的請求。
curl "https://router-api.0g.ai/v1/videos" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-H "X-0G-Provider-Sort: latency" \
-H "X-0G-Provider-Allow-Fallbacks: true" \
-d '{
"model": "minimax-h3",
"prompt": "A cat surfing a wave at sunset",
"seconds": 6
}'