Seedance 2.5 is live — 30-second cinematic video with native audio & real-person references
Seedance 2.5 API Quickstart: Your First Video Request
2026/09/12

Seedance 2.5 API Quickstart: Your First Video Request

Use the Seedance 2.5 API with a key, a valid cURL request and Python polling. Learn input modes, frame chaining and the cost of your first video generation.

To call the Seedance 2.5 API on reAPI, create an API key, send a request to /api/v1/videos/generations with model: "doubao-seedance-2.5-face", then poll the returned id. The completed task contains a video URL. You use the same model id for text, image, first/last-frame and multimodal reference requests.[1]

Start with a four-second text request so there are no uploaded files to diagnose. At the September 12 rate of $0.118589 per second for 480p without reference video, that request costs 475 credits, or $0.475 after credit rounding. The Seedance 2.5 model page has the live rate table and a playground for checking the same settings.[2]

TL;DR

  • Create a Bearer key in API Keys, then send model: "doubao-seedance-2.5-face". The page slug seedance-2-5 is not the request's model id.[1]
  • Submit once, save the response id, and poll /api/v1/tasks/{id}. A successful POST starts a task; it does not mean the video is ready.[1]
  • Choose duration from 4–30 seconds and resolution from 480p, 720p or 1080p. Use a fixed duration for a predictable initial reserve.[1]
  • Set size: "adaptive" for explicit first/last-frame inputs. The output follows the frame shape.[1]
  • A ten-second 720p request without reference video is 2,669 credits, or $2.669, using the September 12 rate. Reference-video billing counts more than output seconds alone.[1][2]

Create a Seedance 2.5 API key and prepare one request

Sign in to reAPI, open API Keys, and create a key for the workspace that will pay for the generation. Copy it into a local environment variable named REAPI_API_KEY. Keep the key out of browser JavaScript, public repositories and screenshots. Requests authenticate through the Authorization: Bearer ... header; the documented workflow does not require a separate project header.[1]

You also need enough credits for the request's initial reserve. Promotional credits, when offered to an eligible account, are separate from whether a particular video can be fully funded. Read the amount shown in your account. This tutorial assumes a funded account and does not promise a free generation.[2]

Keep the first payload small. A prompt, fixed duration, aspect ratio and resolution are enough for a text request. Add images or sound after the submission and polling path works. That makes a failed first attempt easier to diagnose: it cannot be caused by an inaccessible reference URL or incompatible source file.

Send the first cURL request and keep its task id

With REAPI_API_KEY already set in your shell, submit this request:

curl --fail-with-body https://reapi.ai/api/v1/videos/generations \
  -H "Authorization: Bearer $REAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.5-face",
    "prompt": "A matte cobalt ceramic mug stands on an ivory turntable. One continuous studio shot. Over four seconds the turntable rotates clockwise by about 45 degrees. The camera stays fixed at mug height. Keep the handle, rim and glaze consistent. Soft side light, plain background, no text or logos.",
    "duration": 4,
    "size": "16:9",
    "resolution": "480p",
    "generate_audio": false,
    "return_last_frame": true
  }'

Save the response's id before doing anything else. That identifier belongs to this generation and is the value you use for subsequent GET requests. Do not replace it with the model id, a file URL, or a guessed identifier. The response also includes a task status; the video URLs appear when the task completes.[1]

The example requests a last-frame image as well as the video. You can ignore that image for a standalone clip, or use it later when chaining shots. The same prompt and settings are included in our tested prompt library, where you can inspect the generated take instead of treating the wording as a quality guarantee.

Submit and poll a Seedance 2.5 API task in Python

The Python example below is an alternative to the cURL example: it creates a new video task and polls that task. Choose one submission method for your first test. Running both examples creates two paid generations.

The script waits up to 30 minutes locally. That timeout is an example client policy, not a promised generation time. It reports an HTTP failure instead of silently starting another job. Install requests and set REAPI_API_KEY before running it.

import os
import time
import requests

BASE = "https://reapi.ai/api/v1"
headers = {"Authorization": f"Bearer {os.environ['REAPI_API_KEY']}"}
payload = {
    "model": "doubao-seedance-2.5-face",
    "prompt": "A ceramic mug on a table. Locked camera, soft daylight.",
    "duration": 4,
    "resolution": "480p",
    "size": "16:9",
    "generate_audio": False,
}

submitted = requests.post(
    f"{BASE}/videos/generations",
    headers=headers,
    json=payload,
    timeout=120,
)
submitted.raise_for_status()
task_id = submitted.json()["id"]
print("Save this task id:", task_id, flush=True)

deadline = time.monotonic() + 30 * 60
while time.monotonic() < deadline:
    response = requests.get(
        f"{BASE}/tasks/{task_id}", headers=headers, timeout=60
    )
    if response.status_code in (429, 500, 502, 503, 504):
        time.sleep(10)
        continue
    response.raise_for_status()
    task = response.json()
    if task["status"] == "completed":
        for url in task["output"]["video_urls"]:
            print(url)
        break
    if task["status"] == "failed":
        raise RuntimeError(task.get("error"))
    time.sleep(10)
else:
    raise TimeoutError(f"Resume polling existing task {task_id}")

Polling does not consume generation credits. If the local process times out, keep the saved id and resume GET requests for that task. A local timeout alone does not establish that the remote generation failed. Likewise, if a POST connection breaks before you receive a response, check your task history before submitting the same work again.[1]

For a service integration, persist the task id in your own database immediately after submission. The important distinction is between retrying a read of an existing task and creating a new task. The latter is another generation request.

Select four input modes through the media fields

The media fields select the request shape. Use this table alongside the full Seedance 2.5 API documentation.[1]

Intended requestFields to sendConstraint to remember
Text to videopromptA text-only request needs a prompt
Reference image to videoimage_urls plus motion promptPublic image URLs; up to 30 images
Explicit first or first/last frameimage_with_rolesUse size: "adaptive"; a last frame needs a first frame
Multimodal referenceimage_urls, video_urls and/or audio_urlsEach media type has its own file and duration limits

For example, replace the text-only payload's image inputs with an explicit first frame:

{
  "image_with_roles": [
    {
      "url": "https://file.deepytb.com/landing/qwen-image-2/playground-input.webp",
      "role": "first_frame"
    }
  ],
  "size": "adaptive"
}

This block shows fields to merge into a complete request, not a complete POST body. Replace the sample with an image you are entitled to use. Do not send both image_urls and image_with_roles; they are mutually exclusive. Nor should you mix frame roles and reference_image roles in the same array.[1]

For video input, a source clip must be 2–30 seconds long, with at most ten clips and no more than 30 seconds combined. Audio has separate limits of ten tracks and 30 seconds combined. More files do not make a request more controlled by themselves; assign each reference a clear role in the prompt.[1]

Chain a last frame without assuming perfect continuity

Set return_last_frame: true in the first request. When that task completes, read output.last_frame_url and place that URL in the next request's image_with_roles array with role: "first_frame". Use size: "adaptive" again.[1]

Carry forward the relevant description of the subject, clothing, setting and intended next action. A shared boundary image gives the next shot a visual starting point; it does not prove that later frames will preserve every detail. Inspect the join, especially moving hands, eye direction and background objects, before using the pair as one sequence.

Video editing is a different request shape. An explicit omni_reference_task_type: "edit" requires source video, adaptive size and auto duration. It is not the right setting for a new scene that merely uses a photo as guidance. Keep the first integration on a plain generation path, then add editing when you need to modify an existing clip.[1]

Calculate the request cost before adding source video

For requests without reference video, multiply the per-second price by output duration, convert dollars to credits and round up to a whole credit. One credit is $0.001.[1]

RequestSeptember 12 rateCalculationPayable total
4 seconds, 480p, no reference video$0.118589/sceil(0.118589 × 4 × 1000)475 credits / $0.475
10 seconds, 720p, no reference video$0.266824/sceil(0.266824 × 10 × 1000)2,669 credits / $2.669
10-second output, 3-second reference, 720p$0.160094/sceil(0.160094 × 17 × 1000)2,722 credits / $2.722

The last row bills 17 seconds because video-input requests use the larger of output plus rounded source duration and ceil(5 × output / 3). A lower reference-video rate therefore does not necessarily mean a lower final charge. Images and audio references do not add source seconds.[1][2]

Auto duration, duration: -1, reserves against the 30-second cap and later settles to delivered length. Use a fixed duration when the reserve needs to stay small. For broader platform comparisons, see the API pricing guide.

Keep API-host instructions together

Searches for Seedance 2.5 on OpenRouter, fal or GitHub can lead to different clients and service contracts. This tutorial's key, endpoint, model id and task envelope belong together. A repository that calls another service is not a drop-in replacement for this request.

Before adapting a sample, check its base URL, authentication header, accepted model names, input schema and status endpoint. Use the documentation for the host that will actually receive the request. You do not need a third-party GitHub wrapper to run the cURL and Python examples here; they use reAPI's documented HTTP interface.[1]

FAQ

Seedance 2.5 API key

Create a key in reAPI API Keys and use it as a Bearer token. Keep it in your server or local environment, with enough workspace credits for the request.[1]

Seedance 2.5 API documentation

The model reference documents accepted fields, modes, constraints and billing. Use the model page for current per-second prices.[1][2]

Seedance 2.5 API tutorial

Submit one fixed-duration text request, save its id, then poll until completed or failed. Add reference files only after that path works.[1]

Seedance 2.5 API GitHub

A GitHub client is optional. Inspect which service it calls and whether its fields match the current API documentation before using its example payloads.[1]

Seedance 2.5 API access

reAPI exposes doubao-seedance-2.5-face through its asynchronous video endpoint. The website model slug is not the model value to submit.[1]

Seedance 2.5 API cost

A four-second 480p request without source video costs $0.475 after credit rounding at the September 12 rate. Duration, resolution and reference-video billing change the total.[1][2]

Finish one request before expanding the workflow

Keep the first successful payload and its task id as your Seedance 2.5 API integration baseline. For the next request, add the media type your shot needs and check the returned video before introducing chaining or edits.

References

  1. reAPI. Seedance 2.5 API — Parameters, Modes & Billing. Browser-retrieved September 12, 2026. reapi.ai/docs/seedance-2-5.
  2. reAPI. Seedance 2.5 model page, rendered pricing table and FAQ. Browser-retrieved September 12, 2026. reapi.ai/models/seedance-2-5.