Video Extension
Generate new footage that continues an existing video or leads into it (Seedance 2.5 video_extension).
Seedance 2.5 generates new footage that continues an existing video (forward) or leads into it (backward). The result is only the newly generated part, without the video you send: to get the whole video, join the two yourself.
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_extension. |
video_url | string | Yes | The video to extend, at most 30 seconds, see Media. An http(s) link of at most 4096 characters that can be downloaded directly, not a private address. |
extension_mode | string | Yes | forward: continue after the end of the video. backward: generate what comes before its start. |
prompt | string | Yes | What happens in the new part, at most 8000 characters. |
resolution | string | Yes | 480p, 720p or 1080p. Sets the price. |
duration | integer | Yes | Length of the new part in seconds, 4–30. It's what you pay for, see Pricing. |
generate_audio | boolean | No | Whether the new part 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. |
aspect_ratio isn't accepted (the new part follows the video you extend), and neither are image_urls, video_urls and audio_urls: sending any of them returns 400 invalid_request with param set to it (for example aspect_ratio is not allowed for mode video_extension; the output follows the source video).
Continue a video for 5 more seconds, 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_extension",
"video_url": "https://example.com/source.mp4",
"extension_mode": "forward",
"prompt": "Continue the scene smoothly",
"resolution": "720p",
"duration": 5
}'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 new part is at data.outputs[0].url of the retrieved task or the webhook. The task can still fail after it's created (for example the video 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 = duration × price per second of the resolutionLoading the current prices…
Example: the request above (720p, 5 seconds) costs 5 × the 720p price per second.
Billed seconds are the duration of the new part, however long the video you extend is. 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 on the retrieved task is what counts. 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, extension_mode is missing or isn't forward / backward (extension_mode should be 'forward' or 'backward' for mode video_extension), aspect_ratio, image_urls, video_urls or audio_urls was sent, or resolution or duration 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 |
|---|---|---|
invalid_media | The video can't be downloaded or read (corrupt or an unsupported format). Found when the video is downloaded, a few seconds after the task is submitted. The frozen amount is returned in full. | Use a publicly downloadable video link and create the task again. |
video_too_long | The video is longer than 30 seconds (The video duration must be at most 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 (for forward, keep its end; for backward, its start) 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.