# Seedance 2.5

Seedance 2.5 is ByteDance's newest video generation model (Dreamina Seedance 2.5). Send the official ModelArk task body to `POST /v1/videos/generations`, keep the returned task ID, and read the finished video from `GET /v1/tasks/{id}`. Images, videos and audio go in `content` as URLs.

## Model IDs

| Model ID                | Resolutions       | Length                     |
| ----------------------- | ----------------- | -------------------------- |
| `dreamina-seedance-2-5` | 480p, 720p, 1080p | 4–30 seconds, or automatic |

See the [pricing page](https://toklab.ai/pricing) for current prices.

## Quick example

```bash
curl https://api.toklab.ai/v1/videos/generations \
  -H "Authorization: Bearer $TOKLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "dreamina-seedance-2-5",
    "content": [{"type": "text", "text": "A red paper boat drifts across a calm pond at sunrise, slow dolly-in"}],
    "resolution": "720p",
    "ratio": "16:9",
    "duration": 5,
    "generate_audio": true
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.toklab.ai/v1/videos/generations",
    headers={"Authorization": f"Bearer {os.environ['TOKLAB_API_KEY']}"},
    json={
        "model": "dreamina-seedance-2-5",
        "content": [{"type": "text", "text": "A red paper boat drifts across a calm pond at sunrise, slow dolly-in"}],
        "resolution": "720p",
        "ratio": "16:9",
        "duration": 5,
        "generate_audio": True,
    },
    timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]
```

```javascript
const response = await fetch('https://api.toklab.ai/v1/videos/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TOKLAB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'dreamina-seedance-2-5',
    content: [{ type: 'text', text: 'A red paper boat drifts across a calm pond at sunrise, slow dolly-in' }],
    resolution: '720p',
    ratio: '16:9',
    duration: 5,
    generate_audio: true,
  }),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { id: taskId } = await response.json();
```

```go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    body := strings.NewReader(`{
      "model": "dreamina-seedance-2-5",
      "content": [{"type": "text", "text": "A red paper boat drifts across a calm pond at sunrise, slow dolly-in"}],
      "resolution": "720p",
      "ratio": "16:9",
      "duration": 5,
      "generate_audio": true
    }`)
    req, err := http.NewRequest("POST", "https://api.toklab.ai/v1/videos/generations", body)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer " + os.Getenv("TOKLAB_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 60 * time.Second}
    res, err := client.Do(req)
    if err != nil { panic(err) }
    defer res.Body.Close()
    if res.StatusCode != http.StatusOK { panic(res.Status) }
    var task struct { ID string `json:"id"` }
    if err := json.NewDecoder(res.Body).Decode(&task); err != nil { panic(err) }
    fmt.Println(task.ID)
}
```

## Endpoint

```text
POST https://api.toklab.ai/v1/videos/generations
```

| Header        | Value                 |
| ------------- | --------------------- |
| Authorization | `Bearer YOUR_API_KEY` |
| Content-Type  | `application/json`    |

The body is the official ModelArk "create a video generation task" request body; this is the same endpoint every TokLab video model uses. The response is the new task (`id`, `status: "processing"`), not the finished video. Keep API keys in server-side code.

## Parameters

| Name                       | Type      | Required | Default                        | Notes                                                                                                                                     |
| -------------------------- | --------- | -------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `model`                    | string    | Yes      | —                              | `dreamina-seedance-2-5`.                                                                                                                  |
| `content`                  | object\[] | Yes      | —                              | The prompt and media; see below.                                                                                                          |
| `draft`                    | boolean   | No       | `false`                        | `true` creates a 480p draft.                                                                                                              |
| `resolution`               | enum      | No       | `720p` standard / `480p` draft | `480p`, `720p`, `1080p`. A final request from `draft_task` must explicitly specify `1080p`.                                               |
| `ratio`                    | enum      | No       | `adaptive`                     | `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, `adaptive`. Must be `adaptive` (or omitted) with a first frame, and for `edit` and `extend`. |
| `duration`                 | integer   | No       | `-1`                           | 4–30 seconds, or `-1` to let the model choose. Must be `-1` for `edit`.                                                                   |
| `generate_audio`           | boolean   | No       | `true`                         | Generate sound with the video.                                                                                                            |
| `watermark`                | boolean   | No       | `false`                        | Add a watermark.                                                                                                                          |
| `return_last_frame`        | boolean   | No       | `false`                        | Also return the final frame as an image URL.                                                                                              |
| `output_format`            | enum      | No       | `mp4`                          | `mp4` or `mov`.                                                                                                                           |
| `omni_reference_task_type` | enum      | No       | `auto`                         | `auto`, `reference`, `edit`, `extend`. `edit` and `extend` need a reference video.                                                        |
| `execution_expires_after`  | integer   | No       | `172800`                       | 3600–259200 seconds. A task still unfinished after this fails with `task_expired` and is not charged.                                     |
| `priority`                 | integer   | No       | `0`                            | 0–9.                                                                                                                                      |
| `safety_identifier`        | string    | No       | —                              | 1–64 characters identifying your end user. A hash is fine.                                                                                |
| `service_tier`             | enum      | No       | `default`                      | Only `default`.                                                                                                                           |
| `content_filter`           | boolean   | No       | `true`                         | TokLab extension. `false` turns off content filtering on this request.                                                                    |

### `content` items

| Item  | Shape                                                                                   | Role                                           | Limit                      |
| ----- | --------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------- |
| Text  | `{"type": "text", "text": "..."}`                                                       | —                                              | One.                       |
| Image | `{"type": "image_url", "image_url": {"url": "https://..."}, "role": "..."}`             | `first_frame`, `last_frame`, `reference_image` | Up to 30 reference images. |
| Video | `{"type": "video_url", "video_url": {"url": "https://..."}, "role": "reference_video"}` | `reference_video`                              | Up to 10.                  |
| Audio | `{"type": "audio_url", "audio_url": {"url": "https://..."}, "role": "reference_audio"}` | `reference_audio`                              | Up to 10.                  |

Unknown fields are rejected. Not supported: `seed`, `callback_url` (poll the task instead), `tools`, and the 1.x-only `frames` and `camera_fixed`. Tasks cannot be cancelled or deleted.

## Modes

The mode follows from the `content` items; there is no mode parameter.

| Mode                 | `content`                                                                          |
| -------------------- | ---------------------------------------------------------------------------------- |
| Text to video        | one text item                                                                      |
| First frame          | text (optional) + one image with role `first_frame`, or one image with no role     |
| First and last frame | text (optional) + one `first_frame` image + one `last_frame` image                 |
| Multimodal reference | text + any mix of `reference_image`, `reference_video` and `reference_audio` items |
| Edit a video         | text + one `reference_video`, with `omni_reference_task_type: "edit"`              |
| Extend a video       | text + one `reference_video`, with `omni_reference_task_type: "extend"`            |

First-frame modes cannot be combined with reference items. With several images or any other media, every image needs a `role`.

### Reference example

```bash
curl https://api.toklab.ai/v1/videos/generations \
  -H "Authorization: Bearer $TOKLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "dreamina-seedance-2-5",
    "content": [
      {"type": "text", "text": "The character from the image walks through the market in the video, same camera move"},
      {"type": "image_url", "image_url": {"url": "https://example.com/character.png"}, "role": "reference_image"},
      {"type": "video_url", "video_url": {"url": "https://example.com/market.mp4"}, "role": "reference_video"}
    ],
    "ratio": "adaptive",
    "duration": 8
  }'
```

Replace the example URLs with your own accessible files.

## Media inputs

This API accepts URL references only. Base64, `data:` URLs, `asset://` IDs and multipart uploads are not accepted.

Media must be public HTTP(S) URLs and meet the model's official limits:

| Media | Formats                                     | Limits                                                                                                                                                                                                       |
| ----- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Image | JPEG, PNG, WebP, BMP, TIFF, GIF, HEIC, HEIF | Smaller than 30 MB; width and height 300–6000 px; aspect ratio (width / height) 0.4–2.5; 1–30 reference images                                                                                               |
| Video | MP4, MOV (H.264 or H.265)                   | 2–30 seconds each (4–30 seconds for `edit`), up to 10, at most 30 seconds in total; at most 200 MB; 24–60 FPS; width and height 300–6000 px; aspect ratio 0.4–2.5; 407,696–8,295,044 pixels (width × height) |
| Audio | WAV, MP3                                    | 2–30 seconds each, up to 10, at most 30 seconds in total; at most 15 MB                                                                                                                                      |

Reference images and videos that contain real human faces are not supported by the model.

Media is checked when the task starts, before any generation. A task whose media breaks one of these limits ends as `failed` with `invalid_request_error` and a message naming the rule, for example `The request was rejected: content reference videos must total at most 15 seconds.`, and is not charged. A file that cannot be read at that point is passed to the model, which accepts or rejects it; a failed task is not charged either way.

## Pricing dimensions

Check the [pricing page](https://toklab.ai/pricing) for current rates. Seedance 2.5 bills video tokens, the official unit:

```text
video tokens = (output seconds + reference video seconds) × width × height × 24 / 1024
```

The rate per million tokens depends on the output resolution and on whether the request includes a reference video; a request with a reference video uses a lower rate for all of its tokens. Text, image and audio inputs are not billed. At 16:9, one second is 9,607.5 tokens at 480p (854×480), 21,600 at 720p, 48,600 at 1080p.

Requests with reference videos also have a minimum token threshold. For estimates, use at least `ceil(output seconds × 2 / 3)` reference seconds in the formula, even when the original reference videos are shorter. This applies to both draft and final tasks; the draft clip itself does not become a reference video. Actual charges follow the completed task's reported usage.

The charge follows the tokens the finished video reports (`output.usage.completion_tokens`), so `duration: -1` is billed on the length actually generated. Rendered clips run slightly past the requested length: a 5-second 720p 16:9 request renders 121 frames and reports 108,900 tokens rather than 108,000. View final charges in [Task logs](https://toklab.ai/tasks). Failed tasks are not charged.

## Output schema

Submission returns the new task:

```json
{"id": "task_...", "model": "dreamina-seedance-2-5", "status": "processing", "created_at": 1790321515}
```

### Get the task

```bash
curl https://api.toklab.ai/v1/tasks/YOUR_TASK_ID \
  -H "Authorization: Bearer $TOKLAB_API_KEY"
```

Poll every 10–20 seconds until `status` is `completed` or `failed`. A network timeout while polling does not mean generation failed: keep the task ID and resume checking it. Do not create another task to check progress.

### Complete polling example

Run this after the Python submission example above.

```python
import time

deadline = time.monotonic() + 1800
while time.monotonic() < deadline:
    result = requests.get(
        f"https://api.toklab.ai/v1/tasks/{task_id}",
        headers={"Authorization": f"Bearer {os.environ['TOKLAB_API_KEY']}"},
        timeout=30,
    )
    result.raise_for_status()
    task = result.json()
    if task["status"] == "completed":
        print(task["output"]["video_url"])
        break
    if task["status"] == "failed":
        raise RuntimeError(task["error"]["message"])
    time.sleep(15)
else:
    raise TimeoutError(f"Still waiting. Resume polling task {task_id}.")
```

### Completed task

```json
{
  "id": "task_...",
  "model": "dreamina-seedance-2-5",
  "status": "completed",
  "created_at": 1790321515,
  "finished_at": 1790321652,
  "output": {
    "video_url": "https://static.toklab.ai/media/tasks/task_example/0.mp4",
    "last_frame_url": "https://static.toklab.ai/media/tasks/task_example/last_frame/0.jpg",
    "content": {
      "video_url": "https://static.toklab.ai/media/tasks/task_example/0.mp4",
      "last_frame_url": "https://static.toklab.ai/media/tasks/task_example/last_frame/0.jpg"
    },
    "usage": {"completion_tokens": 108900, "total_tokens": 108900},
    "seed": 42,
    "resolution": "720p",
    "ratio": "16:9",
    "duration": 5,
    "framespersecond": 24,
    "generate_audio": true,
    "draft": false,
    "output_format": "mp4",
    "service_tier": "default",
    "execution_expires_after": 172800,
    "priority": 0
  }
}
```

| Field                                                                                           | Meaning                                                         |
| ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `id`                                                                                            | Keep this ID for later queries.                                 |
| `status`                                                                                        | `processing`, `completed` or `failed`.                          |
| `output.video_url`                                                                              | The generated video.                                            |
| `output.last_frame_url`                                                                         | The final frame, when `return_last_frame` is `true`.            |
| `output.content`                                                                                | The same URLs in the official ModelArk shape.                   |
| `output.usage.completion_tokens`                                                                | Video tokens of the finished video; the billed quantity.        |
| `output.duration`, `output.resolution`, `output.ratio`, `output.framespersecond`, `output.seed` | What was actually rendered; `seed` is the one the model picked. |
| `created_at`, `finished_at`                                                                     | Unix timestamps in seconds.                                     |
| `error`                                                                                         | `{"code", "message"}` on a failed task.                         |

Video URLs are hosted on our storage. Save the file to your own storage when you need a durable copy.

## Errors

Requests rejected before a task is created return an HTTP error with an `error` object and are not charged. A task that fails after acceptance returns HTTP 200 when queried, with `status: "failed"` and an `error` object. Output withheld by content filtering fails with `content_policy_violation`; a task that runs past `execution_expires_after` fails with `task_expired`.

See the [shared error catalog](https://toklab.ai/docs/api/errors) for codes, HTTP statuses, and retry guidance.

```json
{
  "id": "task_...",
  "model": "dreamina-seedance-2-5",
  "status": "failed",
  "error": {
    "code": 60001,
    "message": "The request was rejected by the content policy. Please revise the prompt or input images."
  }
}
```

If submission itself times out, check [Task logs](https://toklab.ai/tasks) before submitting again: the first request may have been accepted.

## Tips

* Describe the subject, the action, the camera move, and the lighting in full sentences.
* Draft at 480p with a short `duration`, then render the keeper at a higher resolution.
* Chain shots with `return_last_frame`: use the returned frame as the next task's `first_frame`.
* To edit footage, set `omni_reference_task_type` to `edit` and describe only what should change.

## Pricing

Every rate this model is billed at, read live from the price list billing uses. A tier applies when its condition matches, checked top to bottom.

### dreamina-seedance-2-5

| When | Video (per 1M tokens) |
| --- | --- |
| Resolution: 480p · Reference video: No | $10.681 |
| Resolution: 480p · Reference video: Yes | $6.38 |
| Resolution: 720p · Reference video: No | $10.681 |
| Resolution: 720p · Reference video: Yes | $6.38 |
| Resolution: 1080p · Reference video: No | $11.671 |
| Resolution: 1080p · Reference video: Yes | $6.996 |
| Resolution: 4k · Reference video: No | $10.681 |
| Otherwise | $6.38 |

## Related

* [Seedance 2.5 pricing](https://toklab.ai/pricing)
* [Download OpenAPI](https://toklab.ai/docs/seedance-2-5.openapi.json)
* [Copyable Markdown](https://toklab.ai/docs/seedance-2-5.md)

## Draft preview and final video

Set `draft: true` to generate a 480p preview. Other resolutions are invalid in draft mode. Preview generation uses the same token usage and unit price as standard 480p generation.

```json
{
  "model": "dreamina-seedance-2-5",
  "content": [{ "type": "text", "text": "A fox walks through a sunny garden." }],
  "draft": true,
  "resolution": "480p",
  "duration": 4,
  "ratio": "16:9"
}
```

Poll the returned TokLab task ID until `status` is `completed` and `output.draft` is `true`. Within 7 days of the draft's creation, submit a separate request using that ID:

```json
{
  "model": "dreamina-seedance-2-5",
  "content": [{ "type": "draft_task", "draft_task": { "id": "task_YOUR_DRAFT_ID" } }],
  "resolution": "1080p"
}
```

The draft must belong to your account, have completed, and use the same model. `content` must contain only one `draft_task` item. Explicitly set `resolution` to `1080p`; omit `draft` or set it to `false`. Do not send `duration`, `ratio`, `seed`, `generate_audio`, `omni_reference_task_type`, text, or media again, even with the same values. These settings are inherited from the draft.

You may set `watermark`, `return_last_frame`, `output_format`, `execution_expires_after`, `priority`, `safety_identifier`, and `service_tier: "default"` for the new task. Omitted output options use their defaults. `content_filter` is inherited and cannot be changed. A successful final video returns a new task ID, `output.draft: false`, and `output.draft_task_id` containing your original TokLab draft ID. One draft can be used for multiple separate final generations before it expires.

Draft and final video are billed independently. The final video uses the 1080p rate for **the original draft's input category**: if the draft used reference video, the final also uses the reference-video rate and includes the original reference video's duration in token usage. The draft clip itself is not added as an input video. Each task uses the price in effect when it is submitted. Failed requests are not charged.
