MixMedia API
RUEN
Sign inGet started
Open as Markdown
← Try it on the website

Seedance 2.5

ByteDance · ~4 min
from $0.075per second

ByteDance's newest video model: clips up to 30 seconds with sound, from a description, frames or references.

Seedance 2.5 is the newest ByteDance video model. It films 4 to 30 second clips in 480p, 720p and 1080p with sound: from a description, from the first and last frame, from references (up to 30 photos, 10 clips and 10 audio tracks), and it edits and continues your video.

Pick «Auto» length and the model decides: the price of 30 seconds is held and the rest comes back right after the video is ready.

One model, seedance-2.5 · ~4 min. The result follows the input fields (prompt, frames, references, video_mode, duration) — there are no separate «animate / edit» endpoints.

Features

  • prompt — up to 30000 characters
  • duration: "auto" / -1 — model picks length (on the site: auto (-1))
  • video_mode: auto · reference · edit · extend
  • watermark — "AI generated" mark
  • output_format: mp4 (default) or mov
  • return_last_frame — last-frame URL for chaining
  • generate_audio — audio in the clip
  • nsfw_check — check before charge
  • web_search / tools: [{"type":"web_search"}] — fresh web grounding

Price

ResolutionPrice per secondWith your video, per second
480p$0.125$0.075
720p$0.281$0.169
1080p$0.501$0.299
  • Price = per-second price × clip length, rounded up to $0.001. Charged when the task is created and fully refunded if it fails.
  • With your video, the seconds of the source clip are added to the seconds of the result.
  • On the site — the auto (-1) tick next to the duration (not a list item). In the API: duration: "auto" or -1 lets the model choose the length, up to 30 s. On creation the price of 30 s is charged (plus your video seconds, if any). When the video is ready the price is recalculated from the real length and the difference goes straight back to your balance (history: «Refund for unused video seconds»). The final price is costUsd in recordInfo, the length is duration in resultJson. With video_mode: "edit" the result is as long as your clip.

Media limits

TypeLimits
Imagesup to 30; JPG / PNG / WebP (also BMP / TIFF / GIF / HEIC via public https; or asset://… if you already have an id); upload via files/upload — up to 30 MB per file
Videosup to 10; total ≤ 30 s (each clip 2…30 s); MP4 / MOV → MP4 on the server; upload ≤ 200 MB
Audioup to 10; total ≤ 30 s; MP3 / WAV; upload ≤ 200 MB; audio-only (no photo/video) is allowed

Photos — public https or upload; video and audio — files/upload only.

Task types and constraints

video_modeWhat you needNotes
autoprompt; media optionaldefault; the model picks reference / edit / extend
referencephoto / video / audio referencescharacter, place, motion, style
editvideo_urlslength and aspect ratio follow your clip; clip ≥ 4 s
extendvideo_urlscontinue the clip

Field omni_reference_task_type is an alias of video_mode (accepted by the API).

Tip: with video_urls the site preselects aspect_ratio: adaptive and duration: auto / -1 (auto (-1) tick) — the model is picky about tiny duration mismatches. You can still set other values manually.

480p draft → 1080p final

  1. Create a task with draft: true (resolution forced to 480p).
  2. Wait for success, then POST with draft_task_id = your taskId (no prompt or media). Final is 1080p; reference-video seconds are not billed again.
  3. Only output_format, watermark, return_last_frame may change. Drafts last 7 days. draft and draft_task_id are mutually exclusive.

On the site: «480p draft» tick; on recent works the 1080p button.

Parameters (field input)

ParameterDescriptionValues (default in bold)
promptWhat happens in the clip: scene, motion, camera, light, styletext, up to 30000 chars
first_frame_urlFirst frame: a photo link (https); the video starts from it"https://…"
last_frame_urlLast frame (optional, only together with the first one)"https://…"
image_urlsReference photos (https)["https://…"], up to 30
video_urlsYour videos (MP4): upload them via files/upload first and pass the returned links["https://…"], up to 10
audio_urlsAudio (MP3): upload via files/upload first["https://…"], up to 10
video_modeTask type for your video: auto (default) — the model works it out from the description, reference — reference, edit — edit (length and aspect ratio follow your video), extend — extend. Omitted = autoauto (the model works it out) · reference (reference) · edit (edit) · extend (extend)
resolutionVideo resolution480p (standard) · 720p (high (HD)) · 1080p (Full HD)
aspect_ratioAspect ratioadaptive (matches your upload) · 16:9 (landscape) · 9:16 (portrait) · 1:1 (square) · 4:3 (traditional) · 3:4 (vertical traditional) · 21:9 (ultra-wide)
durationVideo duration in seconds4 to 30 s, or auto / -1 (the model picks the length) (default 5)
generate_audioVideo with soundtrue false (default true)
return_last_frameReturn the last-frame image URL (for continuing the clip)true false (default false)
output_formatResult container: mp4 (default) or movmp4 mov
draftЧерновик 480ptrue false (default false)
web_searchWeb search: fresh information from the internet (real places, events, products)true false (default false)
watermark"AI generated" watermark on the videotrue false (default false)
nsfw_checkContent check: the description and photos are checked first; if not allowed, no task is created and nothing is chargedtrue false (default false)
seedVariant number: the same number with the same prompt gives a similar result; empty or -1 = random-1…4294967295
trim_video_toTrim each of your clips to N seconds: the beginning stays. Shorter clips are not changedwhole number, 2 to 30
trim_to_durationTrim each of your clips to the chosen duration: the beginning stays. With duration: "auto" or video_mode: "edit" — to the model limittrue false (default false)
auto_trimIf your clips together are longer than 30 s, trim them instead of returning an error (the longest first)true false (default false)

Examples

Prompt only

curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","input":{"prompt":"A drone flies over an autumn forest at sunrise, fog, cinematic","resolution":"720p","aspect_ratio":"adaptive","duration":"5"}}'
import os, requests

r = requests.post(
    "https://mixmedia.tech/api/v1/jobs/createTask",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
      "model": "seedance-2.5",
      "input": {
        "prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
        "resolution": "720p",
        "aspect_ratio": "adaptive",
        "duration": "5"
      }
    },
)
print(r.json())  # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "model": "seedance-2.5",
    "input": {
      "prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
      "resolution": "720p",
      "aspect_ratio": "adaptive",
      "duration": "5"
    }
  }),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }

With a first frame

curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","input":{"prompt":"The character slowly turns to the camera, the wind moves the hair","first_frame_url":"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg","resolution":"720p","duration":"5"}}'
import os, requests

r = requests.post(
    "https://mixmedia.tech/api/v1/jobs/createTask",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
      "model": "seedance-2.5",
      "input": {
        "prompt": "The character slowly turns to the camera, the wind moves the hair",
        "first_frame_url": "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg",
        "resolution": "720p",
        "duration": "5"
      }
    },
)
print(r.json())  # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "model": "seedance-2.5",
    "input": {
      "prompt": "The character slowly turns to the camera, the wind moves the hair",
      "first_frame_url": "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg",
      "resolution": "720p",
      "duration": "5"
    }
  }),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }

With references

curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","input":{"prompt":"A drone flies over an autumn forest at sunrise, fog, cinematic","image_urls":["https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"],"resolution":"720p","aspect_ratio":"adaptive","duration":"5"}}'
import os, requests

r = requests.post(
    "https://mixmedia.tech/api/v1/jobs/createTask",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
      "model": "seedance-2.5",
      "input": {
        "prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
        "image_urls": [
          "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
        ],
        "resolution": "720p",
        "aspect_ratio": "adaptive",
        "duration": "5"
      }
    },
)
print(r.json())  # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "model": "seedance-2.5",
    "input": {
      "prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
      "image_urls": [
        "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
      ],
      "resolution": "720p",
      "aspect_ratio": "adaptive",
      "duration": "5"
    }
  }),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }

With your video

curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","input":{"prompt":"Make the clip anime style, keep everything else","video_urls":["https://mixmedia.tech/files/<id>.mp4"],"video_mode":"edit","resolution":"720p","duration":"5"}}'
import os, requests

r = requests.post(
    "https://mixmedia.tech/api/v1/jobs/createTask",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
      "model": "seedance-2.5",
      "input": {
        "prompt": "Make the clip anime style, keep everything else",
        "video_urls": [
          "https://mixmedia.tech/files/<id>.mp4"
        ],
        "video_mode": "edit",
        "resolution": "720p",
        "duration": "5"
      }
    },
)
print(r.json())  # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "model": "seedance-2.5",
    "input": {
      "prompt": "Make the clip anime style, keep everything else",
      "video_urls": [
        "https://mixmedia.tech/files/<id>.mp4"
      ],
      "video_mode": "edit",
      "resolution": "720p",
      "duration": "5"
    }
  }),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }

Trim your video

Your clips together: up to 30 s. No need to cut a long clip beforehand:

  • trim_to_duration: true — trim each clip to the chosen duration;
  • trim_video_to: N — keep N seconds from the start;
  • auto_trim: true — if the clips together are over the limit, cut them exactly to it instead of an error.

Trimming is free, and the price uses the trimmed seconds — fewer seconds cost less.

curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","input":{"prompt":"Make the clip anime style, keep everything else","video_urls":["https://mixmedia.tech/files/<id>.mp4"],"video_mode":"edit","resolution":"720p","duration":"5","trim_to_duration":true,"auto_trim":true}}'
import os, requests

r = requests.post(
    "https://mixmedia.tech/api/v1/jobs/createTask",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
      "model": "seedance-2.5",
      "input": {
        "prompt": "Make the clip anime style, keep everything else",
        "video_urls": [
          "https://mixmedia.tech/files/<id>.mp4"
        ],
        "video_mode": "edit",
        "resolution": "720p",
        "duration": "5",
        "trim_to_duration": True,
        "auto_trim": True
      }
    },
)
print(r.json())  # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "model": "seedance-2.5",
    "input": {
      "prompt": "Make the clip anime style, keep everything else",
      "video_urls": [
        "https://mixmedia.tech/files/<id>.mp4"
      ],
      "video_mode": "edit",
      "resolution": "720p",
      "duration": "5",
      "trim_to_duration": true,
      "auto_trim": true
    }
  }),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }

One uploaded file: up to 30 s. Without these options, clips that are too long return a 400 error with a hint.

Create and result

  1. POST /api/v1/jobs/createTask with model and input.
  2. Poll GET /api/v1/jobs/recordInfo?taskId=… every 3–5 s (or a callback).

Successful createTask (HTTP 200)

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_...",
    "task_id": "task_...",
    "status": "submitted"
  }
}

Completed task (recordInfo)

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_...",
    "task_id": "task_...",
    "state": "success",
    "status": "completed",
    "costUsd": "0.384",
    "refunded": false,
    "resultJson": {
      "videos": [
        {
          "url": "https://…/out.mp4"
        }
      ],
      "duration": 8
    },
    "lastFrameUrl": "https://…/last.jpg"
  }
}

Aliases: task_id = taskId; status: pending / processing / completed / failed alongside state. Clip URL is in resultJson. size is an alias of aspect_ratio in input.

Photos can be any public https links or uploads via files/upload. Videos and audio — via files/upload only.

Error handling

API responses are JSON {"code", "msg", "data"}; errors also have a string error field (type). On /api/v1/* the HTTP status matches body code.

Example response bodies

400

{
  "code": 400,
  "msg": "input.duration: must be between 4 and 30, or \"auto\" / -1",
  "data": null,
  "error": "invalid_request_error"
}

401

{
  "code": 401,
  "msg": "Authentication failed. Please check your API key",
  "data": null,
  "error": "authentication_error"
}

402

{
  "code": 402,
  "msg": "Insufficient balance. Please top up and try again. Available: $0.01, required: $0.015. Top up at https://ai.aimixmedia.site/cabinet/billing",
  "data": {
    "balance": "0.0100",
    "required": "0.0150",
    "currency": "USD",
    "topUpUrl": "https://mixmedia.tech/cabinet/billing"
  },
  "error": "payment_required"
}

429

{
  "code": 429,
  "msg": "Rate limit exceeded: 10 createTask/upload requests per 10 s per key. Retry after 8s",
  "data": null,
  "error": "rate_limit_error"
}

500

{
  "code": 500,
  "msg": "Internal server error",
  "data": null,
  "error": "server_error"
}

Codes on createTask / upload

codeerrorMeaningWhat to do
400invalid_request_errorInvalid parameter or bodySee msg
400unsupported_modelUnknown modelModel list
400nsfw_content_detectedRejected by content check (nsfw_check)Change the prompt or files
401authentication_errorMissing or invalid keyCheck the key
402payment_requiredNot enough balanceTop up
403permission_errorNo accessContact support
429rate_limit_errorToo many requestsWait for Retry-After
505model_disabledModel temporarily disabledPick another
500server_errorOur failureRetry later

Example msg values: Authentication failed. Please check your API key (401); Insufficient balance. Please top up and try again… (402).

Task errors (recordInfo)

If the task was created and then failed: state: "fail" (alias status: "failed"), failCode / failMsg, and error: { code, message, type }. Money is refunded (refunded: true).

failCodeerror.typeMeaning
400nsfw_content_detected / invalid_request_errorModeration / safety rules
422invalid_request_errorThe model rejected the parameters (length, mode, resolution, file)
501server_errorThe model could not generate (failMsg)
504timeout_errorTimed out — retry
500 / 503server_errorService temporarily unavailable

Common refusals for this model

  • duration out of range, or auto / -1 when auto length is not supported (Seedance 2.5 only)
  • resolution / aspect_ratio (size) / video_mode not in the list above
  • video_mode = edit or extend without video_urls; for edit — clip shorter than 4 s
  • Reference video/audio too long without auto_trim / trim_* → 400
  • nsfw_check: true — on reject immediate HTTP 400 (nsfw_content_detected); no task, no charge

Rate limits

WhatLimit
createTask and upload20 per 10 s per key
recordInfo / list / balance100 per 10 s per key

Over the limit — HTTP 429 and Retry-After.

© 2026 MixMedia