von 0G Foundation
ByteDance Seedance 2.5 text-to-video and image-to-video (single first-frame reference via input_reference) — the two Seedance capabilities that map onto a real OpenAI Video API field. ByteDance's own model also supports first+last-frame control and multimodal reference generation (multiple reference images/videos/audio composited per the prompt, including audio-only input), but OpenAI's Video API has no field to express either one, so this integration does not expose a client-facing input for them. Duration 4-30s (default 5); seconds is required on this endpoint and is clamped into that range rather than rejected (the vendor's own 'model-chosen' -1 duration is not reachable through this endpoint — seconds must be a positive number here), resolution 480p/720p/1080p (narrower than earlier Seedance versions — 4k is not served, and is downgraded rather than rejected: a 4K pixel size renders at 1080p, while the bare token '4k' is unrecognised and falls to the 720p default), ratio 16:9/9:16/4:3/3:4/1:1/21:9/adaptive, optional synchronized audio (generate_audio, on by default), fps fixed at 24, optional output_format passthrough (default mp4). Billed on the vendor-reported token count (usage.completion_tokens) — not a flat per-second rate. Async: POST /v1/videos, poll GET /v1/videos/{id} until completed, then GET /v1/videos/{id}/content for the MP4.
$11.7
ab $8.424
pro 1 M Videotokens, die der Anbieter meldet
480p · 720p · 1080p
Abrechnungsstufen – nicht die Größe, die Sie senden
Async-API — Die Videogenerierung verwendet einen asynchronen Ablauf: Reichen Sie einen Auftrag ein, fragen Sie ab, bis er abgeschlossen ist, und laden Sie die Datei dann von einem separaten Endpunkt herunter. Die Generierung dauert Minuten, fragen Sie also alle 3–5 Sekunden ab. Die folgenden Beispiele zeigen alle drei Schritte.
# 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": "bytedance/seedance-2.5",
"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
Anbieter-Routing
Steuern Sie, welcher Anbieter Ihre Anfrage bearbeitet, mit den X-0G-Provider-*-Anfrage-Headern.
X-0G-Provider-Address legt einen Anbieter fest; X-0G-Provider-Identity legt fest, welcher seiner vorgelagerten Dienste für das Routing verwendet wird – beide Werte stammen aus den Feldern address und provider_identity von GET /v1/providers. Zusammen adressieren sie einen bestimmten vorgelagerten Dienst eines Anbieters. Werden beide nicht gesendet, wählt der Router genau wie zuvor anhand von Preis und Zustand aus.
curl "https://router-api.0g.ai/v1/videos" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-H "X-0G-Provider-Address: <PROVIDER_ADDRESS>" \
-H "X-0G-Provider-Identity: <UPSTREAM>" \
-H "X-0G-Provider-Sort: latency" \
-H "X-0G-Provider-Allow-Fallbacks: true" \
-d '{
"model": "bytedance/seedance-2.5",
"prompt": "A cat surfing a wave at sunset",
"seconds": 6
}'