> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# doubao-seedance-2.5 Video Generation

>  - Async API; returns task_id for polling
- Text-to-video / multimodal reference / edit / extend / first–last frame
- Up to 30s per job; up to 30 images + 10 videos + 10 audios as references
- Resolution 480p / 720p only; mp4 or mov output 

<Info>
  **Main changes vs 2.0**: max duration 15s → **30s**; references 9 images + 3 videos + 3 audios → **30 images + 10 videos + 10 audios**; **audio-only** reference supported; **mov** output added.\
  **Note**: resolution is **480p / 720p only** (2.0’s 1080p / 4k are **not** available on 2.5).
</Info>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/v1/videos/generations \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "model": "doubao-seedance-2.5",
      "prompt": "A cinematic 30-second steampunk miniature landscape sequence",
      "size": "16:9",
      "resolution": "720p",
      "duration": 30
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.apimart.ai/v1/videos/generations"

  payload = {
      "model": "doubao-seedance-2.5",
      "prompt": "A cinematic 30-second steampunk miniature landscape sequence",
      "size": "16:9",
      "resolution": "720p",
      "duration": 30,
  }

  headers = {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
  }

  response = requests.post(url, json=payload, headers=headers)

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const url = "https://api.apimart.ai/v1/videos/generations";

  const payload = {
    model: "doubao-seedance-2.5",
    prompt: "A cinematic 30-second steampunk miniature landscape sequence",
    size: "16:9",
    resolution: "720p",
    duration: 30,
  };

  const headers = {
    Authorization: "Bearer <token>",
    "Content-Type": "application/json",
  };

  fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(payload),
  })
    .then((response) => response.json())
    .then((data) => console.log(data))
    .catch((error) => console.error("Error:", error));
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
  )

  func main() {
      url := "https://api.apimart.ai/v1/videos/generations"

      payload := map[string]interface{}{
          "model":      "doubao-seedance-2.5",
          "prompt":     "A cinematic 30-second steampunk miniature landscape sequence",
          "size":       "16:9",
          "resolution": "720p",
          "duration":   30,
      }

      jsonData, _ := json.Marshal(payload)

      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Authorization", "Bearer <token>")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := ioutil.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```

  ```java Java theme={null}
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.URI;

  public class Main {
      public static void main(String[] args) throws Exception {
          String url = "https://api.apimart.ai/v1/videos/generations";

          String payload = """
          {
            "model": "doubao-seedance-2.5",
            "prompt": "A cinematic 30-second steampunk miniature landscape sequence",
            "size": "16:9",
            "resolution": "720p",
            "duration": 30
          }
          """;

          HttpClient client = HttpClient.newHttpClient();
          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(url))
              .header("Authorization", "Bearer <token>")
              .header("Content-Type", "application/json")
              .POST(HttpRequest.BodyPublishers.ofString(payload))
              .build();

          HttpResponse<String> response = client.send(request,
              HttpResponse.BodyHandlers.ofString());

          System.out.println(response.body());
      }
  }
  ```

  ```php PHP theme={null}
  <?php

  $url = "https://api.apimart.ai/v1/videos/generations";

  $payload = [
      "model" => "doubao-seedance-2.5",
      "prompt" => "A cinematic 30-second steampunk miniature landscape sequence",
      "size" => "16:9",
      "resolution" => "720p",
      "duration" => 30
  ];

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "Authorization: Bearer <token>",
      "Content-Type: application/json"
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  echo $response;
  ?>
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "code": 200,
    "data": [
      {
        "status": "submitted",
        "task_id": "task_01KMCGF6BQGN3X28H3KSR50X5T"
      }
    ]
  }
  ```

  ```json 400 theme={null}
  {
    "error": {
      "code": 400,
      "message": "Invalid request parameters",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 401 theme={null}
  {
    "error": {
      "code": 401,
      "message": "Authentication failed. Please check your API key",
      "type": "authentication_error"
    }
  }
  ```

  ```json 402 theme={null}
  {
    "error": {
      "code": 402,
      "message": "Insufficient balance. Please top up and try again",
      "type": "payment_required"
    }
  }
  ```

  ```json 429 theme={null}
  {
    "error": {
      "code": 429,
      "message": "Too many requests. Please try again later",
      "type": "rate_limit_error"
    }
  }
  ```

  ```json 500 theme={null}
  {
    "error": {
      "code": 500,
      "message": "Internal server error. Please try again later",
      "type": "server_error"
    }
  }
  ```
</ResponseExample>

## Authentication

<ParamField header="Authorization" type="string" required>
  Bearer token auth. Get a key from the [API Key page](https://apimart.ai/keys).

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

## Request parameters

<ParamField body="model" type="string" required>
  Fixed value: `doubao-seedance-2.5`
</ParamField>

<ParamField body="prompt" type="string" required>
  Prompt. Reference media with `@图片1` / `@视频1` / `@音频1` (1-based index matching array order). English aliases in prompts may also be used depending on model behavior; keep indices aligned with arrays.

  Example: `"Use @视频1 for first-person framing throughout, @音频1 as BGM, first frame is @图片1"`
</ParamField>

<ParamField body="resolution" type="string" default="720p">
  Resolution — **only**:

  * `480p`
  * `720p` (default)

  Values like `1080p` / `2k` / `4k` return a sync **400**.
</ParamField>

<ParamField body="size" type="string" default="adaptive">
  Aspect ratio (field name `aspect_ratio` is also accepted).

  Values: `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, `adaptive` (default)

  <Warning>
    Edit, extend, and first/last-frame jobs have hard `size` constraints — see [Task types and constraints](#task-types-and-constraints).
  </Warning>
</ParamField>

<ParamField body="duration" type="integer" default="5">
  Duration in seconds:

  * `4` \~ `30`
  * `-1`: model picks duration (pre-charge at the **30s** cap; settle to actual length after completion)

  If omitted: generate and bill **5** seconds.
</ParamField>

<ParamField body="generate_audio" type="boolean" default="true">
  Whether to generate audio (alias field name: `audio`).

  * `true`: with audio (default)
  * `false`: silent video
</ParamField>

<ParamField body="watermark" type="boolean" default="false">
  Add an “AI generated” watermark. Default `false`.
</ParamField>

<ParamField body="seed" type="integer">
  Random seed. Different seeds usually yield different results for the same request; the same seed is similar but not guaranteed identical.
</ParamField>

<ParamField body="output_format" type="string" default="mp4">
  Output container:

  * `mp4` (default)
  * `mov`: higher color precision — **recommended** for edit / extend workflows
</ParamField>

<ParamField body="image_urls" type="array<string>">
  Reference image URLs, all treated as `reference_image`.

  Supports:

  * Public URL: `https://example.com/pic.jpg`
  * Private asset: `asset://cm9xxxxxxxx`

  For first/last frames use `image_with_roles`.

  <Warning>
    * Max **30** images
    * Prefer `image_with_roles` for first/last-frame roles
  </Warning>
</ParamField>

<ParamField body="image_with_roles" type="array<object>">
  Images with explicit roles.

  <Expandable title="Fields">
    <ParamField body="url" type="string" required>
      Image URL or `asset://...`
    </ParamField>

    <ParamField body="role" type="string" required>
      * `first_frame`: first frame (1 image)
      * `last_frame`: last frame (1 image, usually with first frame)
      * `reference_image`: reference image (up to 30 total)
    </ParamField>
  </Expandable>

  Example:

  ```json theme={null}
  [
    {"url": "https://example.com/first.jpg", "role": "first_frame"},
    {"url": "https://example.com/last.jpg", "role": "last_frame"}
  ]
  ```

  <Note>
    If `video_urls` / `audio_urls` are present, `first_frame` / `last_frame` are auto-converted to `reference_image` (multimodal reference job).
  </Note>
</ParamField>

<ParamField body="video_urls" type="array<string>">
  Reference video URLs (`reference_video`). Public URLs or `asset://...`.

  Max **10**; total duration ≤ **30s** (each clip 2\~30s).
</ParamField>

<ParamField body="audio_urls" type="array<string>">
  Reference audio URLs (`reference_audio`). Public URLs or `asset://...`.

  Max **10**; total duration ≤ **30s** (each clip 2\~30s).

  <Note>
    2.5 supports **audio-only** reference (no image/video required).
  </Note>
</ParamField>

<ParamField body="return_last_frame" type="boolean" default="false">
  When `true`, the successful result also includes the last-frame image for chaining.
</ParamField>

<ParamField body="tools" type="array<object>">
  Tool list for enhancements such as web search.

  Example:

  ```json theme={null}
  "tools": [{"type": "web_search"}]
  ```

  <Expandable title="Fields">
    <ParamField body="type" type="string" required>
      Tool type

      Values:

      * `web_search` — web search; generation can ground on online information
    </ParamField>
  </Expandable>
</ParamField>

## Media limits

| Media  | Limits                                                                                                                                                  |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Images | ≤30; jpeg / png / webp / bmp / tiff / gif / heic / heif; aspect ratio \[0.4, 2.5]; side length \[300, 6000]px; each \<30MB                              |
| Videos | ≤10; mp4 / mov (H.264 / H.265 + AAC / MP3); each \[2, 30]s and **total ≤30s**; 480p / 720p; total pixels \[409600, 8295044]; fps \[24, 60]; each ≤200MB |
| Audio  | ≤10; wav / mp3; each \[2, 30]s and **total ≤30s**; each ≤15MB                                                                                           |

## Task types and constraints

The service infers task type from references and **prompt intent**. The last three types hard-constrain `size` / `duration`; violations fail **asynchronously after the job starts** (e.g. `InvalidParameter.TaskTypeConstraint`):

| Task type                | Trigger                                                                       | Constraints                                                                                                         |
| ------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Text-to-video            | Text only                                                                     | None                                                                                                                |
| Reference-to-video       | References + normal descriptive prompt                                        | None. **Avoid** words like “edit / extend / continue / delete / replace” in the prompt to prevent misclassification |
| Video edit               | References + prompt with “edit video / add / delete / modify / replace”, etc. | `size` must be `adaptive`, `duration` must be `-1`; source video 4\~30s                                             |
| Video extend             | References + prompt with “extend forward/backward / continue / sequel”        | `size` must be `adaptive`                                                                                           |
| First / first–last frame | `image_with_roles` uses `first_frame` / `last_frame`                          | `size` must be `adaptive` (also checked at submit time)                                                             |

## Private assets (`asset://`)

Same as [Seedance 2.0 private avatar](/es/api-reference/videos/doubao-seedance-2-0/private-avatar): pass approved asset IDs in `image_urls` / `image_with_roles` / `video_urls` / `audio_urls`:

```json theme={null}
"video_urls": ["asset://cm9xxxxxxxx"]
```

Submitted assets work for **both 2.0 and 2.5**.

## Billing

* Billed by **seconds × resolution tier**.
* **With reference video input**: billable seconds = total input video duration (≤30s) + output duration, at the input-reference rate tier.
* `duration = -1` (auto): pre-charge at the **30s** cap; settle to actual output after completion.
* Omit `duration`: generate and bill **5** seconds.
* Failed jobs or content moderation blocks: **full refund** (charge only on successful output).

## Request examples

### Text-to-video (30s)

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "A cinematic 30-second steampunk miniature landscape sequence",
  "size": "16:9",
  "resolution": "720p",
  "duration": 30
}
```

### Multimodal reference (image + video + audio)

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "Use @视频1 for first-person framing, @音频1 as BGM, first frame is @图片1",
  "image_urls": [
    "https://example.com/pic1.jpg",
    "https://example.com/pic2.jpg"
  ],
  "video_urls": ["https://example.com/ref.mp4"],
  "audio_urls": ["https://example.com/bgm.mp3"],
  "size": "16:9",
  "duration": 11
}
```

### Video edit

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "Edit the video: remove all passers-by in @视频1, keep only the main character",
  "video_urls": ["https://example.com/input.mp4"],
  "size": "adaptive",
  "duration": -1,
  "output_format": "mov"
}
```

### First–last frame

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "The girl in the image says \"cheese\" to the camera, 360-degree orbit shot",
  "image_with_roles": [
    {"url": "https://example.com/first.jpg", "role": "first_frame"},
    {"url": "https://example.com/last.jpg", "role": "last_frame"}
  ],
  "size": "adaptive",
  "duration": 5
}
```

### Private asset

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "A person walking naturally on a city street in sunlight",
  "image_urls": ["asset://cm9xxxxxxxx"],
  "duration": 5,
  "resolution": "720p"
}
```

### Web search

```json theme={null}
{
  "model": "doubao-seedance-2.5",
  "prompt": "Generate a short tech-news video intro based on the latest information",
  "size": "16:9",
  "resolution": "720p",
  "duration": 8,
  "tools": [{"type": "web_search"}]
}
```

## Common errors

| Symptom                                                        | Cause                                                                              |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| 400 `This model only supports 480p or 720p resolution`         | Passed 1080p / 2k / 4k, etc.                                                       |
| 400 `This model only supports duration 4-30 seconds, or -1`    | `duration` out of range                                                            |
| 400 `first_frame/last_frame tasks only support ratio=adaptive` | First/last-frame job with a fixed aspect ratio                                     |
| Async failure (edit / extend style message)                    | Prompt classified as edit/extend but `size` / `duration` violate that type’s rules |
| Async failure `SensitiveContentDetected`                       | Media or output failed moderation                                                  |

## Response

<ResponseField name="code" type="integer">
  Status code; `200` on success
</ResponseField>

<ResponseField name="data" type="array">
  Submit response with `status` / `task_id`

  <Expandable title="Array item">
    <ResponseField name="status" type="string">
      Initially `submitted`
    </ResponseField>

    <ResponseField name="task_id" type="string">
      Task ID for [status polling](/es/api-reference/tasks/status)
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  Poll with [Get task status](/es/api-reference/tasks/status). On success use `result.videos[0].url` (stored for long-term access). With `return_last_frame=true`, the result also includes the last-frame image.
</Note>

## Differences from 2.0

| Feature            | 2.0                         | 2.5                                   |
| ------------------ | --------------------------- | ------------------------------------- |
| Model              | `doubao-seedance-2.0`, etc. | `doubao-seedance-2.5`                 |
| Duration           | \~4–15s                     | **4–30s**, or `-1` auto               |
| Resolution         | 480p / 720p / 1080p / 4k    | **480p / 720p only**                  |
| Reference images   | ≤9                          | **≤30**                               |
| Reference videos   | ≤3, total \~\<15s           | **≤10, total ≤30s**                   |
| Reference audio    | ≤3, total ≤15s              | **≤10, total ≤30s**; audio-only OK    |
| Output format      | Mainly mp4                  | **mp4 / mov**                         |
| Watermark          | —                           | `watermark`                           |
| Private `asset://` | Supported                   | **Shared** with the same private APIs |
