Video Edit
Change an existing video as your prompt says, optionally with reference images (Seedance 2.5 video_edit).
Seedance 2.5 changes an existing video as your prompt says, for example replacing an object or changing the style, optionally with reference images. The output keeps the length and aspect ratio of the video you edit.
Create a task
https://api.nanoapi.ai/v1/tasksUse the shared create endpoint with model: "seedance-2.5". It usually responds in under 1 second and the cost is frozen within a few seconds; the video usually takes several minutes. Get the result once the task has finished.
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <API key>, see Authentication. |
Content-Type | Yes | application/json |
Idempotency-Key | No | A unique string for every new task, ideally a UUID (1–255 characters). See Preventing duplicate tasks. |
Body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | seedance-2.5. |
mode | string | Yes | video_edit. |
video_url | string | Yes | The video to edit: 4–30 seconds, see Media. An http(s) link of at most 4096 characters that can be downloaded directly, not a private address. |
prompt | string | Yes | How to change it, at most 8000 characters. Refer to the files as @Video1 (the video to edit) and @Image1 on, see Referring to files. |
image_urls | string[] | No | Up to 30 reference images (for example the object to put in). Each is an http(s) link of at most 4096 characters that can be downloaded directly, not a private address. |
resolution | string | Yes | 480p, 720p or 1080p. Sets the price. |
generate_audio | boolean | No | Whether the output has sound, default true. Same price either way. |
webhook_url | string | No | Notified when the task succeeds or fails: https, up to 2048 characters, not a private, loopback or reserved address. See Webhooks. |
duration and aspect_ratio aren't accepted (the output follows the video you edit), and neither are video_urls and audio_urls: sending any of them returns 400 invalid_request with param set to it (for example duration is not allowed for mode video_edit; the output is as long as the source video).
Output length and billing
- Output length: about as long as the video you edit, sometimes slightly shorter (a 4-second video gives about 3.7 seconds).
- Billed seconds: the output length rounded up to a whole second; less than 0.05 seconds over doesn't count (10.02 s is billed as 10 seconds, 10.06 s as 11). The 3.7-second output above is billed as 4.
- Billing: 30 × the price per second is frozen first; when the task succeeds, the billed seconds are charged and the rest returned, see Pricing.
- Balance: your available balance (and the key's spend limits) must cover the 30 seconds, even if the video is shorter; otherwise the task fails with
insufficient_balance(orspend_limit_exceeded).
Replace the car in the video with the one in the reference image, 720p:
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"mode": "video_edit",
"video_url": "https://example.com/source.mp4",
"image_urls": ["https://example.com/car.jpg"],
"prompt": "Edit @Video1: replace the car with the one in @Image1",
"resolution": "720p"
}'Response: 200 OK. data is the newly created task, with only these fields; each one is described in Create a task: Response. Keep data.id to get the result: once the task succeeds, the video is at data.outputs[0].url of the retrieved task or the webhook. The task can still fail after it's created (for example a file can't be downloaded), so go by what retrieving the task or the webhook tells you.
{
"code": 200,
"message": "success",
"data": {
"object": "task",
"id": "tk_01jbd2s8x4c6v9b3n5m7q1w4e8",
"model": "seedance-2.5",
"status": "queued",
"error": null,
"created_at": "2026-10-31T08:30:00Z"
}
}Pricing
cost = billed seconds of the output × price per second of the resolutionLoading the current prices…
Example: the request above freezes 30 × the video_edit 720p price per second first. When the task succeeds, the billed seconds × the price per second are charged and the rest returned: for a 10-second output, 10 seconds are charged and 20 returned. billing.billed_seconds is then the billed output length. If the task fails, all of it is returned.
video_edit has its own price per second, separate from the other modes. Prices change, so read the current ones from GET /v1/products (the prices rows whose mode is this mode) instead of hard-coding them; billing.frozen and billing.charged on the retrieved task are what count. All Seedance 2.5 prices: Seedance 2.5 → Pricing.
Errors
Create request errors: the request fails with an HTTP error and no task is created. Specific to this mode:
| Status | error.type | When | What to do |
|---|---|---|---|
400 | invalid_request | video_url or prompt is missing, duration, aspect_ratio, video_urls or audio_urls was sent (aspect_ratio is not allowed for mode video_edit; the output follows the source video), image_urls has more than 30 images, or resolution isn't one of the values above. param names the parameter. | Fix the parameter param names and send the request again. |
Other errors of the create endpoint (401, 402, 429 and so on): Create a task → Errors.
Task failures: the create request succeeded (200) and the task later turned failed. There's no HTTP status: the reason is the task's error.type, from retrieving the task or the webhook.
error.type | When | What to do |
|---|---|---|
insufficient_balance | Your available balance can't cover 30 seconds at the price per second, even if the video is shorter. Within a few seconds of creating the task, nothing frozen. | Top up, then create the task again. |
invalid_media | The video or a reference image can't be downloaded or read (corrupt or an unsupported format). Found when the files are downloaded, a few seconds after the task is submitted. The frozen amount is returned in full. | Make sure video_url and image_urls can be downloaded publicly, then create the task again. |
video_too_short | The video is shorter than 4 seconds (The video duration must be between 4 and 30 seconds.). Found when the video is downloaded, a few seconds after the task is submitted (started_at may be null). The frozen amount is returned in full. | Use a video of 4–30 seconds and create the task again. |
video_too_long | The video is longer than 30 seconds. Found when the video is downloaded, a few seconds after the task is submitted (started_at may be null). The frozen amount is returned in full. | Trim the video to 30 seconds or less and create the task again. |
Failure reasons shared by every mode (such as a balance too low for the task): Seedance 2.5 → Errors; all of them: Failure reasons.