In shortFrom BytePlus ModelArk, change two lines — the base URL to https://models.dawnwood.ai/v1 and the key to a Dawnwood token — because Dawnwood Models accepts the ModelArk request body, path and task object as they are. From fal, the request is reshaped once - the prompt and image URLs become items in a content array, aspect_ratio becomes ratio, duration becomes an integer - and polling moves from fal's status and response URLs to one GET on the task id. Both paths are shown side by side below.


dw_pat_v1_…) with the model_api scope; it is shown once.Dawnwood Models serves the ModelArk content-generation task path as an alias, takes the same body (model, content[], resolution, ratio, duration, generate_audio) and returns the same task object with the same status values. The official dreamina-seedance-… model ids are accepted, and so are the short ids (seedance-2.0-fast, seedance-2.0-mini, seedance-2.0, seedance-2.5).
# before
BASE = "https://ark.ap-southeast.bytepluses.com/api/v3"
KEY = os.environ["ARK_API_KEY"]
# after
BASE = "https://models.dawnwood.ai/v1"
KEY = os.environ["DAWNWOOD_API_KEY"] # dw_pat_v1_...
# unchanged
H = {"Authorization": f"Bearer {KEY}"}
task = requests.post(f"{BASE}/contents/generations/tasks", headers=H, json=body).json()
status = requests.get(f"{BASE}/contents/generations/tasks/{task['id']}", headers=H).json()
Two differences to know about. Video reference inputs (video_url items) are not supported yet and return 400 unsupported_content. And 1080p is not offered yet; requests use 480p or 720p.
fal exposes each Seedance variant as its own endpoint and takes a flat body. Dawnwood Models has one endpoint, selects the model with a field, and takes inputs as a typed content array.
# before: fal queue API
r = requests.post("https://queue.fal.run/bytedance/seedance-2.0/reference-to-video",
headers={"Authorization": f"Key {os.environ['FAL_KEY']}"},
json={"prompt": prompt,
"image_urls": [lead_png, room_png],
"resolution": "720p", "aspect_ratio": "9:16", "duration": "5"}).json()
# poll r["status_url"] until COMPLETED, then GET r["response_url"] -> ["video"]["url"]
# after: Dawnwood Models
H = {"Authorization": f"Bearer {os.environ['DAWNWOOD_API_KEY']}"}
task = requests.post("https://models.dawnwood.ai/v1/video/generations", headers=H, json={
"model": "seedance-2.0",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": lead_png}, "role": "reference_image"},
{"type": "image_url", "image_url": {"url": room_png}, "role": "reference_image"},
],
"resolution": "720p", "ratio": "9:16", "duration": 5,
}).json()
# poll GET /v1/video/generations/{id} until status is succeeded -> ["content"]["video_url"]
| fal | Dawnwood Models |
|---|---|
| One endpoint per model | One endpoint; model field selects the model |
Authorization: Key … | Authorization: Bearer dw_pat_v1_… |
prompt | content[] item {"type": "text", "text": …} |
image_urls[] (reference-to-video) | content[] items of type image_url, role reference_image |
image_url / end_image_url (image-to-video) | image_url items with role first_frame / last_frame |
audio_urls[] | audio_url items, role reference_audio |
video_urls[] | Not supported yet |
aspect_ratio | ratio |
duration as a string | duration as an integer |
status_url / response_url | GET /v1/video/generations/{id} |
COMPLETED, result video.url | succeeded, content.video_url (valid 24 hours) |
Prompt syntax that refers to reference images by position carries over, because the images keep their order in content[].
Idempotency-Key header with each create call; a retried request returns the same task and is never charged twice.429 with Retry-After; wait and resubmit.billing.refunded is true.{"error": {"code": …, "message": …}}, so existing error handling keeps working.The full schema is in the API reference and as an OpenAPI 3.1 file at dawnwood.ai/models/openapi.json. Prices per model are on the pricing comparison.
Seedance 2.0 Fast, Mini, 2.0 and 2.5 over a ModelArk-compatible API, billed per output second, only for generations that succeed. Making a whole series instead of single clips? The same token can drive the full production pipeline.
Get an API keyModels and prices →Or start a series →