Seedance 2.5 Video Generation API
Detailed APIMaster guide to Seedance 2.5 parameters, reference media, first and last frames, editing, asynchronous results, billing, and troubleshooting.
Seedance 2.5 Video Generation
Create videos from text, images, video, or audio references using the public model ID seedance-2.5. Generation is asynchronous: submit one request, save its public task ID, poll until it finishes, and download the result. A successful submission means the task was accepted; it does not mean a video has already been generated.
Important for frame, edit, and extend tasks: the default ratio is
adaptive. Keep that value or omit the ratio; do not explicitly send a fixed ratio such as16:9. For an image-only first/last-frame task, the output follows the first image’s proportions. Crop or pad your image first if you need a particular ratio.
Default changes — 2026-10-01: omitted
durationnow means5seconds instead of4; the default ratio isadaptiveinstead of16:9; generated audio defaults totrue. Set these fields explicitly if your integration depends on a fixed duration, ratio, or silent output.
Authentication and endpoints
The API base URL is https://apimaster.ai/v1. Get an APIMaster key from API keys and send Authorization: Bearer YOUR_API_KEY. JSON requests also need Content-Type: application/json. Keep keys on your server, not in public frontend code.
| Method | Endpoint | Purpose |
|---|---|---|
POST |
https://apimaster.ai/v1/videos/generations |
Recommended JSON task submission |
GET |
https://apimaster.ai/v1/video/generations/{task_id} |
Compatibility-format task status |
GET |
https://apimaster.ai/v1/videos/{task_id} |
OpenAI-style video status |
GET |
https://apimaster.ai/v1/videos/{task_id}/content |
Authenticated video download |
GET |
https://apimaster.ai/v1/videos/{task_id}/last-frame |
Authenticated last-frame download, when requested |
Do not use an image-task endpoint to poll a video. Use a key belonging to the account that created the task.
Quick start: text-to-video
Start with a short clip and an explicit specification before requesting 30 seconds or higher resolution. Replace example media URLs in later examples with your own directly downloadable files.
curl --fail-with-body -sS "https://apimaster.ai/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "A lighthouse above a calm sea at sunrise. Slow camera push-in, natural lighting, no text.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "adaptive",
"generate_audio": true,
"watermark": false,
"output_format": "mp4"
}'
Example submission response:
{
"code": 200,
"data": [{"status": "submitted", "task_id": "task_example"}],
"error": null
}
Save the returned task_id and use the query endpoint to obtain the task status and final video.
Request parameters and defaults
| Field | Type | Default | Contract |
|---|---|---|---|
model |
string | None; required | seedance-2.5 |
prompt |
string | None; required for generation | Scene, motion, camera, and reference intent; omit when using draft_task_id |
duration |
integer | 5; omitted in edit becomes -1 |
4–30 seconds or -1 for automatic duration; editing accepts only -1 |
resolution |
string | 720p; preview 480p; preview upgrade 1080p |
Ordinary generation: 480p, 720p, 1080p; preview and upgrade accept only their respective resolution |
aspect_ratio |
string | adaptive |
adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9; frame/edit/extend tasks require adaptive |
ratio |
string | Same as aspect_ratio |
Alias; both values must match if supplied together |
size |
string | adaptive when omitted |
Legacy size/ratio convenience field; adaptive is accepted. Prefer resolution and aspect_ratio |
image_urls |
string[] | No references | At most 30 images in total, including image_with_roles |
image_with_roles |
object[] | No references | Objects with url and role; first_frame, last_frame, or reference_image |
first_frame_image / last_frame_image |
string | No frame | Aliases for the corresponding image roles; use HTTP(S) or an approved asset:// URL |
video_urls |
string[] | No references | At most 10; total duration at most 30 seconds |
audio_urls |
string[] | No references | At most 10; total duration at most 30 seconds; audio-only references are supported |
generate_audio |
boolean | true |
Whether to generate sound |
audio |
boolean | Same as generate_audio |
Alias; conflicting audio values return 400 |
watermark |
boolean | false |
Whether to request a generated-content watermark |
seed |
integer | Model-selected | Preserve 0 as an explicit seed; a seed does not guarantee identical output |
output_format |
string | mp4 |
mp4 or mov; MOV is useful for editing/extension workflows. Codec and color precision depend on the resulting file |
omni_reference_task_type |
string | auto |
auto, reference, edit, or extend; see synchronous validation below |
nsfw_check |
boolean | false |
Optional pre-submission text/image moderation |
return_last_frame |
boolean | false |
Return last_frame_url after success when the frame is available |
draft |
boolean | false |
Generate a 480p preview; only seedance-2.5 |
draft_task_id |
string | Not set | Public APIMaster ID of a successful preview; upgrades it to a new 1080p task |
Use JSON booleans, not strings such as "false". Conflicting aliases, unsupported resolutions, invalid duration, and task-specific constraints return HTTP 400 before a task is created or its reservation charged. Omitted optional arrays mean no references.
Additional fields and input forms
| Field or input | Interface support |
|---|---|
negative_prompt |
Accepted as text; included in moderation when nsfw_check is enabled |
first_frame_image / last_frame_image |
Supported string aliases; do not duplicate the same frame in image_with_roles |
| Base64 / data-URL images | Not supported as generation URLs. Upload the file through /v1/uploads/images and use the returned URL |
generation_type |
Accepted as an optional field for ordinary generation; use omni_reference_task_type for the task-type contract |
camerafixed |
Accepted as a boolean for ordinary generation; describe required camera motion in the prompt |
service_tier |
Optional for ordinary generation; rejected for both previews and preview upgrades |
Do not depend on generation_type, camerafixed, or service_tier to guarantee a specific visual result or scheduling priority. They are not substitutes for the documented task-type and prompt requirements.
Select the task type
| Task | Input and intent | Required settings |
|---|---|---|
| Text-to-video | Prompt without reference media | Choose a supported ratio, resolution, and duration |
| Reference generation | Reference images/video/audio and a description of a new scene | Fixed ratios are possible; make the prompt clearly describe reference generation |
| First-frame generation | One image with role first_frame |
aspect_ratio: "adaptive" |
| First-and-last-frame generation | One first_frame and one last_frame |
aspect_ratio: "adaptive"; a last frame needs a first frame |
| Video editing | Source video plus a prompt asking to edit, remove, replace, or modify content | aspect_ratio: "adaptive", duration: -1; source video 4–30 seconds |
| Video extension | Source video plus a prompt asking to continue or extend it | aspect_ratio: "adaptive"; keep reference media within the limits below |
omni_reference_task_type can explicitly select auto, reference, edit, or extend. Use a matching prompt: declaring reference while asking to replace an object can still lead to a task-type mismatch. For editing, omitted duration is normalized to -1; omitted ratio is adaptive. Explicit values must satisfy the same constraints. For reference generation, avoid editing or extension instructions unless that is your intended operation.
Synchronous task-type validation
| Declared type | Validation before acceptance |
|---|---|
edit |
At least one video_urls entry; ratio omitted or adaptive; duration omitted or -1; source video 4–30 seconds |
extend |
At least one video_urls entry; ratio omitted or adaptive |
reference |
Ordinary supported ratio and duration limits apply; no edit/extend restriction |
auto |
Task intent is inferred from the prompt and references |
Explicit selection catches invalid parameters at submission: HTTP 400, no task, no generation reservation. Task intent is also evaluated during generation; a prompt inconsistent with the declared type may fail asynchronously with InvalidParameter.TaskTypeMismatch. Write an editing prompt for edit, a continuation prompt for extend, and a new-scene prompt for reference.
Image roles and first/last frames
image_with_roles entries use {"url": "https://example.com/frame.png", "role": "first_frame"}. Roles are first_frame, last_frame, and reference_image. Use at most one first frame and one last frame. Reference images guide appearance or composition; they do not force an exact starting frame. Avoid mixing overlapping image_urls and image_with_roles definitions.
If video or audio references are also included, frame roles can be treated as general reference images rather than a strict first/last-frame task. Use image-only input when you need precise frame anchoring.
{
"model": "seedance-2.5",
"prompt": "The camera moves smoothly from the first view to the last view. Preserve the building and lighting.",
"image_with_roles": [
{"url": "https://example.com/first.png", "role": "first_frame"},
{"url": "https://example.com/last.png", "role": "last_frame"}
],
"duration": 5,
"resolution": "720p",
"aspect_ratio": "adaptive",
"generate_audio": false
}
For a single starting frame, remove the last_frame entry. If you need a different output ratio, crop or pad the first image to that ratio before submitting; changing only aspect_ratio is not sufficient.
Image, video, and audio references
Give each reference a clear purpose in the prompt. References are indexed from 1 in array order; descriptions such as @图片1, @视频1, and @音频1 can identify image, video, and audio references. Do not refer to an index that is absent from the request.
{
"model": "seedance-2.5",
"prompt": "Create a new coastal scene using @图片1 for the color palette, @视频1 for camera movement, and @音频1 for the rhythm. Do not edit or extend the original video.",
"image_urls": ["https://example.com/palette.png"],
"video_urls": ["https://example.com/camera-reference.mp4"],
"audio_urls": ["https://example.com/rhythm.mp3"],
"omni_reference_task_type": "reference",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"generate_audio": true
}
For audio-only reference generation, keep audio_urls and remove the image/video arrays. All media must be accessible to the generation service without a browser login, cookies, or additional authorization headers.
Edit a video
{
"model": "seedance-2.5",
"prompt": "Edit the video: replace the red umbrella with a blue umbrella while preserving the subject and camera motion.",
"video_urls": ["https://example.com/source.mp4"],
"omni_reference_task_type": "edit",
"duration": -1,
"resolution": "720p",
"aspect_ratio": "adaptive",
"generate_audio": true,
"output_format": "mov"
}
Editing follows the source clip's duration. Automatic duration can require a larger initial balance reservation; see billing below.
Extend a video
{
"model": "seedance-2.5",
"prompt": "Extend the video forward: the cyclist continues along the same path, keeping the lighting and camera direction consistent.",
"video_urls": ["https://example.com/source.mp4"],
"omni_reference_task_type": "extend",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "adaptive",
"generate_audio": true
}
Reference-media requirements
These are input-media limits, not output dimensions. A file that downloads successfully can still be rejected because its real format, dimensions, duration, or content is unsuitable.
| Input | Count | Dimensions and duration | File requirements |
|---|---|---|---|
| Images | At most 30 reference images; frame mode uses one or two images |
Each side 300–6000 pixels; width/height ratio 0.4–2.5 |
Each file below 30 MB. JPEG/PNG are recommended; other accepted formats include WebP, BMP, TIFF, GIF, HEIC, HEIF, subject to decoding support |
| Videos | At most 10; combined duration at most 30 seconds |
Each clip 2–30 seconds; editing source 4–30 seconds. Each side 300–6000 pixels; ratio 0.4–2.5; pixel count 409600–8295044; 24–60 FPS |
Each file at most 200 MB; MP4/MOV with H.264 or H.265 video and AAC or MP3 audio; supported resolution tiers 480p, 720p, 1080p |
| Audio | At most 10; combined duration at most 30 seconds |
Each clip 2–30 seconds |
Each file at most 15 MB; WAV or MP3 |
Use direct HTTPS file URLs rather than a sharing page's HTML URL. A .png filename does not make an HTML error page a valid image. Ensure temporary signed URLs remain valid long enough for the task to fetch the media. Avoid redirects to login pages and links restricted by IP or anti-hotlink rules. For maximum image compatibility, convert the file to RGB JPEG or PNG and verify its actual width and height.
Only upload media you are authorized to use. Content checks can reject realistic-person imagery or other restricted material; do not assume a publicly reachable URL guarantees acceptance.
Upload and review media before generation
APIMaster supports image-file uploads and the Seedance media library. These are separate steps: uploading a file gives you a downloadable URL; submitting that URL to the library starts content review. Only an approved library asset can be referenced with asset:// in a generation request. Ordinary non-person reference media can still use direct public URLs without a library submission.
The library is especially useful when you will reuse a material or its original URL is temporary. After review succeeds, reuse the returned asset:// address; future references use the approved material rather than requiring you to resubmit its original URL. Keep the material in your library for as long as you need to reference it.
Real-person media must first be submitted to the media library and pass review. A successful file upload, a reachable URL, or a successful review-task submission does not mean the material is approved. Use only media you are authorized to upload and use. Review approval does not guarantee that every later generation request will pass its own content checks.
The recommended sequence is: upload an image if you need a public file URL → submit material for review → poll the review task → select an Active asset → submit video generation → poll the video task. Save the returned IDs from each step; use the documented video-query endpoints for video generation.
Material specifications and preparation
The reference-media table above also applies to library submissions. Check the actual decoded file, not just its extension. For Seedance 2.5:
| Material | Accepted formats | File limit | Technical requirements |
|---|---|---|---|
| Image | JPEG, PNG, WebP, BMP, TIFF, GIF, HEIC, HEIF; RGB JPEG/PNG recommended | Below 30 MB per library source |
Width and height each 300–6000 pixels; width/height ratio 0.4–2.5 |
| Video | MP4, MOV; H.264/H.265 video; AAC/MP3 audio when present | At most 200 MB per file |
Each clip 2–30 seconds; editing source 4–30 seconds; each side 300–6000 pixels; ratio 0.4–2.5; total pixels 409600–8295044; frame rate 24–60 FPS; supported tiers 480p, 720p, 1080p |
| Audio | WAV, MP3 | At most 15 MB per file |
Each clip 2–15 seconds |
A review submission contains 1–20 assets of one type. This batch limit differs from the generation limits: up to 30 images, 10 videos, or 10 audio clips; referenced videos together must not exceed 30 seconds, and referenced audio together must not exceed 30 seconds. Uploading 20 materials does not allow all 20 videos or audio clips to be used in one generation.
Explicitly submit model: "seedance-2.5" for video sources up to 30 seconds. The library submission default is seedance-2.0, which limits individual video sources to 15 seconds. Audio-library intake currently has a separate 15-second limit, as explained below. Approved materials may be reused across Seedance 2.0 and 2.5 when the requested model is available to your key and the material satisfies that model's limits.
Audio-library intake: submit individual audio clips between 2 and 15 seconds, even with model: "seedance-2.5". This is separate from generation’s 2–30-second audio-reference limit. Trim or split longer sources; the generation request still permits at most 10 audio references totaling at most 30 seconds.
Video review errors: acceptance of a review request does not establish that a video is usable. A review can fail with FormatUnsupported or Unsupported media format. Check the actual container, codec, dimensions, frame rate, audio track, and URL accessibility; reference a library video only after it becomes Active. Real-person videos require review approval before generation.
Use an HTTP(S) URL that directly downloads the file without login, cookies, extra authorization headers, or anti-hotlink restrictions. Keep signed URLs valid throughout retrieval and review, and keep their content unchanged. Sharing-page HTML, expired links, private-network addresses, broken codecs, or misleading file extensions can cause rejection. Upload video and audio to your own file storage and submit their direct URLs; the image-file upload endpoint below does not accept video or audio.
Step 1: upload a local image file
Send multipart form data to POST https://apimaster.ai/v1/uploads/images with one field named file. Do not manually set a JSON content type: your HTTP client must supply the multipart boundary.
curl --fail-with-body -sS "https://apimaster.ai/v1/uploads/images" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@./reference.png"
Example response:
{
"url": "https://apimaster.ai/imgs/media_upload_example.png",
"filename": "reference.png",
"content_type": "image/png",
"bytes": 123456,
"created_at": 1790812800
}
This endpoint accepts JPEG, PNG, GIF, and WebP only, with a maximum file size of 20 MiB (20 × 1024 × 1024 bytes). It verifies the detected image format and readable image dimensions; a successful upload does not validate every Seedance requirement or approve the content. Images larger than this upload limit, and library-compatible formats absent from this list, need your own public file storage.
The returned URL uses APIMaster's domain and is publicly readable by anyone who knows the URL. It is intended for API media input, rather than permanent archival storage; keep your original file and do not assume a guaranteed retention period. Do not upload confidential content that should require download authentication. Reuse the URL in the next step, or directly in a generation request when library review is not required.
Step 2: submit materials for review
Submit JSON to POST https://apimaster.ai/v1/seedance2/private-avatar/assets. Set either a new group or an existing APIMaster group_id, never both. Omitting both creates a new group automatically.
curl --fail-with-body -sS "https://apimaster.ai/v1/seedance2/private-avatar/assets" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"group": {"name": "My reference materials", "description": "Approved generation references"},
"project_name": "default",
"asset_type": "Image",
"assets": [
{"url": "https://apimaster.ai/imgs/media_upload_example.png", "name": "reference-portrait"}
]
}'
For video or audio, use asset_type: "Video" or asset_type: "Audio" with direct URLs in the same assets structure. Do not mix types within one submission.
| Field | Type | Requirement and behavior |
|---|---|---|
model |
string | Use seedance-2.5 for this guide; default is seedance-2.0 |
group |
object | Optional new group: name up to 255 characters, description up to 4000 characters |
group_id |
string | Optional existing group ID returned by APIMaster; must belong to your account |
project_name |
string | Optional; currently only default is supported |
asset_type |
string | Case-sensitive Image, Video, or Audio; default Image |
assets |
object[] | Required array containing 1–20 materials of the selected type |
assets[].url |
string | Required public HTTP(S) file URL; maximum 8192 characters |
assets[].name |
string | Optional display name, up to 255 characters; an automatic name is used if omitted |
Example accepted response:
{
"code": 200,
"data": {
"id": "asset_task_example",
"object": "seedance.avatar.asset.task",
"model": "seedance-2.5",
"status": "processing",
"progress": 0,
"group_id": "group_example"
}
}
Save data.id as the review-task ID and data.group_id for later submissions. An HTTP success response only confirms acceptance. Do not construct an asset ID from a filename or the task ID.
Step 3: poll the review task and select approved assets
Poll GET https://apimaster.ai/v1/tasks/{review_task_id} every 5–10 seconds until data.status becomes completed or failed. This endpoint is for the material-review task; use the video endpoints documented elsewhere on this page for video generation.
curl --fail-with-body -sS "https://apimaster.ai/v1/tasks/asset_task_example" \
-H "Authorization: Bearer YOUR_API_KEY"
Example completed response; timestamp and source-URL fields are omitted here for brevity:
{
"code": 200,
"data": {
"id": "asset_task_example",
"object": "seedance.avatar.asset.task",
"model": "seedance-2.5",
"status": "completed",
"progress": 100,
"group_id": "group_example",
"result": {
"assets": [{"id": "asset_example", "asset_id": "asset_example", "asset_url": "asset://asset_example", "name": "reference-portrait", "asset_type": "Image", "group_id": "group_example", "status": "Active"}],
"usable_assets": [{"id": "asset_example", "asset_id": "asset_example", "asset_url": "asset://asset_example", "name": "reference-portrait", "asset_type": "Image", "group_id": "group_example", "status": "Active"}],
"failed_assets": []
}
}
}
Review-task states are processing, completed, and failed. Material states are Pending, Active, and Failed; only Active materials may be referenced. Use the returned asset_url unchanged. It identifies an approved library material and is not an HTTP download URL.
A batch can partially succeed. One rejected material can make the overall review task failed while other materials are already Active. Inspect result.usable_assets and result.failed_assets, rather than discarding every item when the task fails. A failure before material results are available may return a safe error message without a result. Correct and resubmit only the rejected inputs; avoid repeating accepted ones.
Poll the review task before relying on the library list: lists do not automatically poll pending review tasks. Task queries and asset details return the public material IDs used by subsequent requests.
Step 4: generate with an approved material
Use an approved asset_url in image_urls, image_with_roles[].url, video_urls, or audio_urls, matching the material type. This first-frame example uses the approved image:
{
"model": "seedance-2.5",
"prompt": "The person slowly turns toward the camera, natural lighting, gentle camera movement.",
"image_with_roles": [{"url": "asset://asset_example", "role": "first_frame"}],
"aspect_ratio": "adaptive",
"duration": 5,
"resolution": "720p",
"generate_audio": false
}
Submit this JSON to POST https://apimaster.ai/v1/videos/generations, then poll the returned video task as described below. An asset approved under one account cannot be used by another account. Keep the IDs returned by APIMaster; IDs copied from another service will not work. Materials combined in one request must come from a compatible library context; if unavailable, create them together in the same APIMaster group and retry after review. Deleting a material prevents future requests from referencing it.
If a request using library assets cannot be submitted, check its status and your task history before submitting again. Avoid immediate duplicate generation requests, especially after a network timeout.
List, inspect, rename, and delete materials
All endpoints require an APIMaster API key. The library is scoped to your account, so keys belonging to the same account can access its resources; another account's resources return HTTP 404. List operations return only your account's materials and groups.
| Method | Endpoint | Purpose |
|---|---|---|
POST |
https://apimaster.ai/v1/seedance2/private-avatar/groups |
Create a group using model, name, and optional description |
GET |
https://apimaster.ai/v1/seedance2/private-avatar/groups |
List your groups |
GET |
https://apimaster.ai/v1/seedance2/private-avatar/groups/{group_id} |
Inspect a group |
PATCH |
https://apimaster.ai/v1/seedance2/private-avatar/groups/{group_id} |
Update name and/or description |
DELETE |
https://apimaster.ai/v1/seedance2/private-avatar/groups/{group_id} |
Delete an empty group |
POST |
https://apimaster.ai/v1/seedance2/private-avatar/assets |
Submit a review batch |
GET |
https://apimaster.ai/v1/seedance2/private-avatar/assets |
List your materials |
GET |
https://apimaster.ai/v1/seedance2/private-avatar/assets/{asset_id} |
Inspect a material and refresh its review status |
PATCH |
https://apimaster.ai/v1/seedance2/private-avatar/assets/{asset_id} |
Update the display name |
DELETE |
https://apimaster.ai/v1/seedance2/private-avatar/assets/{asset_id} |
Delete a material |
GET |
https://apimaster.ai/v1/tasks/{review_task_id} |
Query a review task |
List queries accept page (default 1) and limit (default 20, range 1–100). The material list also accepts your group_id and a case-sensitive status filter. Its response is {"code":200,"data":{"items":[],"total":0,"page":1,"limit":20}}; the items use the same public fields as material/group details. List results do not include resources created outside APIMaster.
Examples:
# List approved materials in a group.
curl --fail-with-body -sS "https://apimaster.ai/v1/seedance2/private-avatar/assets?group_id=group_example&status=Active&page=1&limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"
# Rename one material without changing the source file.
curl --fail-with-body -sS -X PATCH "https://apimaster.ai/v1/seedance2/private-avatar/assets/asset_example" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"approved-reference"}'
# Delete a material before deleting its group.
curl --fail-with-body -sS -X DELETE "https://apimaster.ai/v1/seedance2/private-avatar/assets/asset_example" \
-H "Authorization: Bearer YOUR_API_KEY"
Group creation defaults to seedance-2.5; supply model explicitly for clarity. Display-name changes do not replace the material file or repeat review. To replace media, submit a new review. Pending materials that do not yet have a completed review cannot be renamed or deleted and return HTTP 409. Delete every material in a group before deleting the group; non-empty groups return HTTP 409. A successful delete returns {"code":200,"data":{"id":"asset_example","deleted":true}} (a group deletion returns its group ID).
Charges, rate limits, and errors
Image-file upload, material review, and library CRUD operations have no generation charge and do not create video-usage billing records. Video generation using approved materials is billed normally according to the selected model and references. Free library operations still require a valid authorized key and remain subject to API-key/model rate limits. Upload and creation endpoints additionally limit requests per IP; space requests instead of sending large bursts.
| HTTP status | Meaning | Suggested action |
|---|---|---|
400 |
Invalid JSON, fields, URL, image data, type, or batch size | Check the schema and actual file properties |
401 / 403 |
Missing/invalid key or insufficient model permission | Verify your APIMaster key and allowed models |
404 |
Unknown, deleted, or inaccessible material/group/review task | Use IDs returned to the same account |
400 / 409 |
Material not yet ready, incompatible material context, or non-empty group | Finish review, use a compatible group, or remove group members |
413 |
Image upload exceeds the file/body-size limit | Reduce the file size or use your own public storage |
429 |
Request rate limit reached | Reduce concurrency and retry queries with backoff |
502 / 503 |
Review service unavailable or invalid response | Retry queries first; retain existing task and material IDs |
A review task can return HTTP 200 with data.status: "failed"; inspect the task state and its safe error message, rather than relying only on the HTTP code. Read the returned explanation and keep the public review-task ID for support.
Media-library FAQ
- How long does review take? Poll every
5–10seconds. Duration varies by material and service workload; video and real-person review can take longer than image review. An accepted submission is not approval. - What if review fails without an explanation? Inspect the review task and
failed_assets; keep its public task/asset IDs for support. Check format and URL accessibility before submitting corrected material. A query does not restart a failed review. - Must I upload again for 2.0 versus 2.5? An approved APIMaster asset may be reused when your key has access to the target model and the material meets that model’s limits. Cross-platform IDs cannot be reused.
- Can a batch partly succeed? Yes. Reuse only
usable_assetswhose status isActive; correct rejected items individually. - What does a synchronous material error mean? HTTP 400 rejects invalid input.
invalid_asset_materialmay identifyassets[0],assets[1], and so on; indexes begin at zero. Correct the indicated item’s format or duration before submitting again.
{
"error": {
"message": "invalid_asset_material: assets[0] video duration must be from 2 to 30 seconds",
"type": "media_library_error"
}
}
Preview mode: 480p draft to 1080p final
A preview is a normal billable generation with draft: true. It is valid for upgrades for 7 days from the preview task’s creation time. Each upgrade is an independent task and charge; the same unexpired successful preview can be upgraded multiple times.
Step 1: generate and poll a preview
curl --fail-with-body -sS "https://apimaster.ai/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","prompt":"A colorful abstract pattern gently moves.","draft":true,"duration":5,"return_last_frame":true}'
Omitted resolution becomes 480p. Sending 720p or 1080p with draft: true returns 400. Poll the returned public ID through /v1/videos/{task_id} or /v1/video/generations/{task_id} and wait for success before upgrading. Other generation parameters and media limits apply normally.
Step 2: create a final video from the preview
curl --fail-with-body -sS "https://apimaster.ai/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","draft_task_id":"task_preview_example","output_format":"mp4","return_last_frame":true,"watermark":false}'
The response contains a new public task ID. Omitted resolution becomes 1080p; all other resolution values return 400. Use an API key belonging to the preview’s account. A missing, foreign, non-preview, incomplete, expired, or different-model task is rejected synchronously with 400, without creating a task or charging a reservation.
If the preview is temporarily unavailable, retry later with the same draft_task_id. Do not replace it with another platform’s ID. A preview upgrade cannot be rerouted to a different generation context.
Inherited fields and permitted changes
Do not resend inherited fields, even when their value is identical, false, 0, or null:
prompt, image_urls, image_with_roles, video_urls, audio_urls, duration, size, aspect_ratio, ratio, seed, generate_audio, audio, omni_reference_task_type, generation_type, camerafixed, web_search, tools.
The same restriction applies to APIMaster’s input aliases and legacy wrapper: seconds, images, image, input_reference, first_frame_image, last_frame_image, video_list, negative_prompt, metadata.
Besides model, draft_task_id, and the fixed 1080p resolution, the adjustable fields are only output_format, return_last_frame, and watermark. Omitted values use mp4, false, and false, respectively. The last-frame and watermark flags do not inherit from the preview. Do not combine draft_task_id with draft: true. Both preview creation and upgrade reject service_tier.
Preview and final-video reservations
| Preview duration | Preview reservation | Final-video reservation |
|---|---|---|
Explicit 4–30 seconds |
Specified duration at 480p; reference-video work included normally | Same duration at the 1080p tier without video input |
-1, including omitted duration in edit |
Up to the 30-second maximum | Up to 30 seconds at 1080p without video input |
| Other omitted duration | 5 seconds at 480p | 5 seconds at 1080p without video input |
Preview work follows ordinary 480p pricing; reference-video duration counts normally, with combined billable duration capped at 30 seconds. Final-video work uses the 1080p tier without video input, excluding the preview’s reference-video duration. Success settles actual usage and refunds or charges the difference; failure refunds the full reservation. Pricing comes from your model card and wallet records.
Optional text and image moderation
nsfw_check defaults to false. On Seedance 2.0 and 2.5, setting it to true enables pre-submission checks of prompt, negative_prompt, and image inputs: image_urls, image_with_roles[].url, first/last-frame aliases, and image-type library assets. Generation URLs do not accept base64 images; upload an image file first. Video, audio, and video/audio-type assets are outside this text/image check.
A detected violation returns HTTP 400 with the following response structure; no video task or generation reservation is created:
{
"code": "nsfw_content_detected",
"message": "Your request was rejected by content moderation (`nsfw_check` is enabled). Flagged categories: sexual.",
"data": null
}
This optional check has no generation charge and is not an absolute content-safety guarantee. A check failure or absence of detection does not establish that a later generation will be approved. Use only authorized, compliant content regardless of the flag.
Query status and download
The same task can be read through either query format. Poll at a moderate interval, such as every 5–10 seconds, and stop at a terminal state. Generation time depends on workload, clip duration, resolution, and references; do not treat a slow task as a reason to create duplicate tasks.
curl --fail-with-body -sS "https://apimaster.ai/v1/video/generations/task_example" \
-H "Authorization: Bearer YOUR_API_KEY"
curl --fail-with-body -sS "https://apimaster.ai/v1/videos/task_example" \
-H "Authorization: Bearer YOUR_API_KEY"
curl --fail-with-body -L "https://apimaster.ai/v1/videos/task_example/content" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o output.mp4
Completed responses
Compatibility format, GET /v1/video/generations/{task_id}:
{
"code": "success",
"message": "",
"data": {
"task_id": "task_example",
"status": "succeeded",
"url": "https://apimaster.ai/v1/videos/task_example/content",
"format": "mp4",
"error": null,
"metadata": null,
"usage": {"completion_tokens": 108900},
"actual_time": 160,
"last_frame_url": "https://apimaster.ai/v1/videos/task_example/last-frame"
}
}
OpenAI-style format, GET /v1/videos/{task_id}:
{
"id": "task_example",
"object": "video",
"model": "seedance-2.5",
"status": "completed",
"progress": "100%",
"url": "https://apimaster.ai/v1/videos/task_example/content",
"usage": {"completion_tokens": 108900},
"actual_time": 160,
"last_frame_url": "https://apimaster.ai/v1/videos/task_example/last-frame"
}
| Meaning | Compatibility location | OpenAI-style location |
|---|---|---|
| Public task ID | data.task_id |
id |
| Waiting | data.status: queued |
status: queued |
| Generating | data.status: processing |
status: in_progress |
| Success | data.status: succeeded |
status: completed |
| Failure | data.status: failed |
status: failed |
| Video download URL | data.url |
url |
| Completion tokens | data.usage.completion_tokens |
usage.completion_tokens |
| Elapsed seconds | data.actual_time |
actual_time |
| Last-frame image URL | data.last_frame_url |
last_frame_url |
| Failure explanation | data.error.message |
error.message |
| Output container | data.format |
Use requested output_format when saving |
| Legacy metadata | data.metadata, currently null |
Not used |
actual_time is completion time minus submission time, in seconds, including waiting time; it is not the video’s duration. usage.completion_tokens is the recorded generation statistic and matches the consumption log’s token count. APIMaster’s monetary settlement uses video duration and its applicable tier; the token statistic is not a monetary price formula. Responses contain no amount fields; use your wallet’s consumption records for settlement.
Usage may be absent just after completion; query again later. last_frame_url is returned only after success when you requested return_last_frame: true and a last frame is available. The field is omitted, rather than set to null, when not requested, still pending, or failed. Preview upgrades use their own flag.
Failed response
A failed task is still queried with HTTP 200. The OpenAI-style response can contain:
{
"id": "task_example",
"object": "video",
"model": "seedance-2.5",
"status": "failed",
"progress": "100%",
"error": {"code": "task_failed", "message": "[upstream_error] Unsupported media format."}
}
The compatibility format places the explanation at data.error.message. Failed tasks have no video or last-frame download. Preserve the public task ID and explanation for support.
Download video and last frame
Send Authorization: Bearer YOUR_API_KEY when downloading either URL. Use a key belonging to the task’s account. Video content is MP4 or MOV according to the request; save MOV with a .mov extension. A last frame is an image, so use the returned content type when selecting its extension.
curl --fail-with-body -L "https://apimaster.ai/v1/videos/task_example/last-frame" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o last-frame.jpg
Download and save successful files promptly. Availability is not indefinite; retaining a task ID does not guarantee that its output file remains downloadable. If the file is no longer available, download returns HTTP 410 with error.message: "Media has expired or is no longer available". An unavailable or unrequested last frame returns HTTP 404. Missing download authentication returns HTTP 401.
Python: submit, poll, and save
import os
import time
import requests
base = "https://apimaster.ai/v1"
headers = {"Authorization": f"Bearer {os.environ['APIMASTER_API_KEY']}"}
payload = {
"model": "seedance-2.5",
"prompt": "A lighthouse above a calm sea, slow camera push-in, no text.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "adaptive",
"generate_audio": True,
"watermark": False,
"return_last_frame": True,
}
response = requests.post(f"{base}/videos/generations", headers=headers,
json=payload, timeout=60)
response.raise_for_status()
created = response.json()
data = created.get("data")
if isinstance(data, list) and data:
task_id = data[0].get("task_id")
else:
item = data if isinstance(data, dict) else created
task_id = item.get("task_id") or item.get("id")
if not task_id:
raise RuntimeError("No task ID returned; inspect the submission response.")
print("task_id:", task_id)
# Example client timeout, not a promised generation deadline.
deadline = time.monotonic() + 1800
while time.monotonic() < deadline:
response = requests.get(f"{base}/videos/{task_id}", headers=headers, timeout=60)
response.raise_for_status()
task = response.json()
state = task.get("status")
if state == "failed":
error = task.get("error") or {}
raise RuntimeError(error.get("message", "Video generation failed."))
if state == "completed":
result = requests.get(f"{base}/videos/{task_id}/content", headers=headers,
timeout=120, stream=True)
result.raise_for_status()
with open("output.mp4", "wb") as output:
for chunk in result.iter_content(1024 * 1024):
if chunk:
output.write(chunk)
print("Saved output.mp4")
print("usage:", task.get("usage"), "actual_time:", task.get("actual_time"))
if task.get("last_frame_url"):
frame = requests.get(task["last_frame_url"], headers=headers, timeout=60)
frame.raise_for_status()
with open("last-frame.jpg", "wb") as image:
image.write(frame.content)
print("Saved last-frame.jpg")
break
time.sleep(5)
else:
raise TimeoutError(f"Task {task_id} is still pending; keep this ID and query it later.")
A connection timeout during submission leaves the outcome uncertain: keep any returned task ID and check your task history before submitting again. A polling timeout does not cancel a task. Avoid automatic retries of a billable submission when you do not know whether it was accepted.
Billing, reservations, and refunds
Billing uses duration in seconds and depends on resolution, input-media type, and your applicable account price. Generated versus silent audio does not select a separate pricing tier in the current Seedance 2.5 configuration. Check the model card and the wallet's video/media pricing before submission; this page does not hardcode a changing price.
- Submission reserves an estimated amount. Omitted ordinary duration reserves
5seconds. Forduration: -1, the estimate uses the30-second maximum, so enough balance is needed even if the result is shorter. - With reference video, billable work can include reference-video duration plus generated-video duration. A
5-second output is not necessarily billed as only5seconds of work. - After successful generation, final measured usage can produce an additional charge or a refund of the difference. Use the final wallet records to confirm settlement.
- Failed tasks refund the generation reservation. A failed task may still show its original consumption record together with a matching refund; count both when checking the net charge.
- Correcting an invalid request requires a new submission. An existing failed task ID cannot be restarted by continuing to poll it.
JavaScript, Go, Java, and PHP examples
These examples submit a text-to-video task and print its response. Save data[0].task_id, then use the query/download flow above. Read your key from the server environment.
JavaScript (Node.js)
const response = await fetch("https://apimaster.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIMASTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "seedance-2.5", prompt: "A lighthouse at sunrise, slow camera push-in.",
duration: 5, resolution: "720p", aspect_ratio: "adaptive",
generate_audio: true, watermark: false, output_format: "mp4",
}),
});
const body = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${body}`);
console.log(JSON.parse(body));
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
payload, err := json.Marshal(map[string]any{
"model": "seedance-2.5", "prompt": "A lighthouse at sunrise, slow camera push-in.",
"duration": 5, "resolution": "720p", "aspect_ratio": "adaptive",
"generate_audio": true, "watermark": false, "output_format": "mp4",
})
if err != nil { panic(err) }
req, err := http.NewRequest("POST", "https://apimaster.ai/v1/videos/generations", bytes.NewReader(payload))
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer " + os.Getenv("APIMASTER_API_KEY"))
req.Header.Set("Content-Type", "application/json")
response, err := (&http.Client{Timeout: 60 * time.Second}).Do(req)
if err != nil { panic(err) }
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil { panic(err) }
if response.StatusCode >= 400 { panic(fmt.Sprintf("HTTP %d: %s", response.StatusCode, body)) }
fmt.Println(string(body))
}
Java (JDK 11+)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class SeedanceExample {
public static void main(String[] args) throws Exception {
String json = "{\"model\":\"seedance-2.5\",\"prompt\":\"A lighthouse at sunrise.\","
+ "\"duration\":5,\"resolution\":\"720p\",\"aspect_ratio\":\"adaptive\","
+ "\"generate_audio\":true,\"watermark\":false,\"output_format\":\"mp4\"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apimaster.ai/v1/videos/generations"))
.timeout(Duration.ofSeconds(60))
.header("Authorization", "Bearer " + System.getenv("APIMASTER_API_KEY"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)).build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
throw new RuntimeException("HTTP " + response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
}
}
PHP
<?php
$payload = [
'model' => 'seedance-2.5', 'prompt' => 'A lighthouse at sunrise, slow camera push-in.',
'duration' => 5, 'resolution' => '720p', 'aspect_ratio' => 'adaptive',
'generate_audio' => true, 'watermark' => false, 'output_format' => 'mp4',
];
$handle = curl_init('https://apimaster.ai/v1/videos/generations');
curl_setopt_array($handle, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('APIMASTER_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
]);
$body = curl_exec($handle);
if ($body === false) { throw new RuntimeException(curl_error($handle)); }
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) { throw new RuntimeException("HTTP $status: $body"); }
print_r(json_decode($body, true, 512, JSON_THROW_ON_ERROR));
Migrating from another Seedance 2.5 integration
Set your base URL to https://apimaster.ai/v1 and submit to POST /v1/videos/generations. Use this page’s APIMaster field definitions and defaults; keep duration, ratio, and audio explicit when migrating an existing integration.
Use GET /v1/video/generations/{task_id} or GET /v1/videos/{task_id} for videos. /v1/tasks/{id} also serves media-review tasks; for an APIMaster video ID it returns the compatibility video response. Prefer the two dedicated video endpoints to keep video and review handling clear.
| Other integration | APIMaster compatibility | APIMaster OpenAI style |
|---|---|---|
pending |
data.status: queued |
status: queued |
processing |
data.status: processing |
status: in_progress |
completed |
data.status: succeeded |
status: completed |
failed |
data.status: failed |
status: failed |
data.result.videos[].url[0] |
data.url |
url |
| Last-frame result | data.last_frame_url |
last_frame_url |
| Generation usage | data.usage.completion_tokens |
usage.completion_tokens |
| Elapsed time | data.actual_time |
actual_time |
Download video and last-frame URLs with your account’s Bearer key. APIMaster returns no amount fields; use wallet consumption records. Task IDs, asset:// IDs, and draft_task_id are specific to APIMaster and cannot be copied across platforms. Submit and review your materials again in APIMaster. Save outputs promptly rather than assuming the retention period of another service applies.
Seedance 2.0 and 2.5 differences
Use the specific model’s documentation when changing models. Limits are not inferred from a model’s version number.
| Capability | Seedance 2.0 | Seedance 2.5 |
|---|---|---|
| Public model | seedance-2.0 |
seedance-2.5 |
| Default duration | 4 seconds |
5 seconds; editing defaults to -1 |
| Generation duration | Consult the 2.0 model’s documented mode | 4–30 seconds, or -1 |
| Resolution | 480p, 720p, 1080p, 4K |
480p, 720p, 1080p |
| Image/video/audio count and total duration | Follow the 2.0 model’s media limits | 30 images, 10 videos totaling at most 30 seconds, 10 audio clips totaling at most 30 seconds |
| Pure audio reference | Follow the 2.0 model’s documented mode | Supported |
| Output format | mp4, mov |
mp4, mov |
| Watermark | Follow the 2.0 model’s documented options | false by default |
| Preview and upgrade | Not supported by this workflow | 480p preview → 1080p final; valid for 7 days |
| Media-library video intake default | Individual video limit 15 seconds |
Individual video limit 30 seconds when explicitly selected |
| Media-library audio intake | 2–15 seconds |
2–15 seconds |
Approved asset:// references |
Same account’s approved assets, subject to model permissions and limits | Same rule; cross-platform IDs are not accepted |
Error response structures
Submission validation returns HTTP 400 with an error object:
{
"error": {
"message": "draft resolution must be 480p",
"type": "invalid_request_error"
}
}
Some request-rejection paths use a code / message / data envelope, including moderation and invalid media inputs:
{
"code": "invalid_request",
"message": "Invalid format for image_with_roles[0].url. Only http/https URLs or asset:// private asset URLs are supported.",
"data": null
}
Missing download authentication returns HTTP 401:
{
"error": {
"code": "",
"message": "Invalid token (request id: request_example)",
"type": "new_api_error"
}
}
Handle both error envelopes: read error.message when present, otherwise message. Do not require a single error-code field to detect failure. A video-query HTTP 200 may still contain a failed task.
| Submission message | Meaning |
|---|---|
unsupported seedance-2.5 resolution "4k" |
Use a supported resolution |
seedance-2.5 duration must be -1 or an integer from 4 to 30 |
Duration outside the allowed range |
first/last frame aspect_ratio must be adaptive |
Image-only frame task uses a fixed ratio |
edit requires at least one video_urls entry |
Missing editing source |
extend requires at least one video_urls entry |
Missing extension source |
edit duration must be -1 |
Explicit editing duration is not automatic |
draft resolution must be 480p |
Preview resolution is invalid |
draft_task_id resolution must be 1080p |
Upgrade resolution is invalid |
draft and draft_task_id cannot be used together |
Mutually exclusive preview fields |
service_tier is not supported for draft tasks |
Scheduling field supplied for preview or upgrade |
draft_task_id was not found in your account |
Missing or inaccessible preview ID |
draft_task_id is not a draft task |
Ordinary task supplied as a preview |
draft_task_id has not completed successfully |
Preview pending or failed |
draft_task_id has expired; drafts are valid for 7 days |
Preview older than 7 days |
draft_task_id model does not match |
Source model differs |
Draft is temporarily unavailable; retry with the same draft_task_id later |
Retry later without changing the preview ID |
prompt must not be supplied with draft_task_id |
Inherited field resubmitted; equivalent errors name other forbidden fields |
Troubleshooting
Distinguish a synchronous submission error from an asynchronous failure: HTTP 200 with a task ID only confirms acceptance. The task can later become failed.
| Error or symptom | Likely cause | What to do |
|---|---|---|
Invalid ratio / first-frame ratio must follow the image |
Fixed ratio used in a frame task | Set aspect_ratio: "adaptive"; crop/pad the first image if a specific ratio is needed |
Invalid content[1] / invalid image format |
A URL returns HTML, an expired link, or an unsupported/undecodable image | Open the direct file URL without login; convert to JPEG/PNG; verify dimensions and retry with a new task |
| Image side or aspect ratio out of range | An image is too small/large or too wide/tall | Each side 300–6000 pixels; width/height 0.4–2.5 |
InvalidParameter.TaskTypeConstraint |
Edit/extend/frame settings violate their task-specific contract | Use adaptive; editing also needs duration: -1 |
InvalidParameter.TaskTypeMismatch |
Declared task type and prompt intent disagree | Rewrite the prompt and select a matching omni_reference_task_type |
| Content rejected / moderation blocked | Input or prompt violates applicable content rules | Use compliant media and revise the prompt; do not retry the same rejected content unchanged |
HTTP 400 |
Missing prompt, unsupported resolution/duration, invalid media, or conflicting aliases | Check the request against this page before resubmitting |
HTTP 401 / 403 |
Invalid key or insufficient authorization | Use an active APIMaster key from the account that owns the task |
Insufficient balance, including HTTP 402 or a balance/quota error |
Available wallet/key allowance cannot cover the reservation | Check wallet balance, key allowance, and automatic-duration reservation |
HTTP 429 |
Rate or concurrency limit | Back off; reuse the existing task ID when polling |
HTTP 500 / 502 / network timeout |
Temporary service or connection failure | Retry reads with backoff; check task history before retrying a submission |
| Task completed but download fails | Downloading too early, missing authentication, or unavailable output | Query state again, send the same account's key, and keep the task ID for support |
The user task log and usage-log details show safe failure explanations. When contacting support, include the public task ID, approximate submission time, model, resolution, duration, and relevant error message. Never send your API key or authorization header.
Related: Video API overview · Seedance 2.0
