APIMaster.ai

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 as 16: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 duration now means 5 seconds instead of 4; the default ratio is adaptive instead of 16:9; generated audio defaults to true. 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–10 seconds. 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_assets whose status is Active; correct rejected items individually.
  • What does a synchronous material error mean? HTTP 400 rejects invalid input. invalid_asset_material may identify assets[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 5 seconds. For duration: -1, the estimate uses the 30-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 only 5 seconds 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