Skip to content
GhostmotionGhostmotion / DevelopersOpen app
Seedance API

Seedance 2.5 at BytePlus’s price

Generate clips with Seedance 2.5 (dreamina-seedance-2-5-260628) through your Ghostmotion workspace. It is BytePlus ModelArk’s own task API, with the same request body and task shape, so a BytePlus client changes only two things.

Base URL · replaces https://ark.ap-southeast.bytepluses.com/api/v3
https://app.ghostmotion.ai/api/v1/seedance

And its key: send a Ghostmotion API key as Authorization: Bearer. The same keys, workspace credits and spending limits apply as for the video API. The Seedance API is available where your workspace has it; Integrations shows it when it does.

Price

Exactly BytePlus’s: its list price per million output tokens for the clip’s resolution (lower when a video is among the inputs), times the tokens the clip used, at one credit per US dollar. A 6-second 1080p clip that used 293,625 tokens costs 3.435413 credits. When BytePlus can’t make a task, the same task is made by another provider and still costs what BytePlus would have charged. A clip that isn’t made costs nothing.

1. Create a task

Terminal
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedance/contents/generations/tasks" \
  -H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "dreamina-seedance-2-5-260628",
  "content": [
    {
      "type": "text",
      "text": "A red kite over a beach at dusk, slow push-in"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/first-frame.jpg"
      },
      "role": "first_frame"
    }
  ],
  "resolution": "1080p",
  "duration": 6,
  "request_id": "kite-001"
}'

The body is BytePlus’s: content holds one text item and any images (first_frame, last_frame or reference_image), reference videos and audio, as public https URLs. Set resolution (480p, 720p, 1080p), ratio and duration (4–30 seconds, or -1 for automatic). Fields BytePlus has but this API does not take, such as callback_url, are refused by name. Add request_id to retry without starting a second task.

2. Check it until it ends

Terminal
export TASK_ID='ID_FROM_RESPONSE'

curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedance/contents/generations/tasks/$TASK_ID" \
  -H "Authorization: Bearer $GHOSTMOTION_API_KEY"

Wait poll_after_seconds between checks. At succeeded, content.video_url is a link valid for one hour (read the task again for a fresh one), usage.completion_tokens is what the clip used, and credits.charged what it cost. A failed task’s error says why; it was not charged.

Through MCP

Where your workspace has the Seedance API, MCP clients also get create_seedance_task and get_seedance_task, with the same inputs and results.

Reference

POST

Create a Seedance video

POST /api/v1/seedance/contents/generations/tasks

Generate a clip with Seedance 2.5 (dreamina-seedance-2-5-260628), in BytePlus ModelArk's own request shape. Returns the task id at once; poll get_seedance_task until it succeeds or fails. Costs exactly BytePlus's price, one credit per US dollar.

Required permission: videos:write

A BytePlus client only changes its base URL to {origin}/api/v1/seedance and its key. The price is BytePlus's list price for the tokens the clip used; when BytePlus can't make a task, the same task is made by another provider at the same price. Nothing made, nothing charged. The most a task could cost is held while it runs. Reuse request_id and the same body to retry without a second task.

Request body

request_idstring · optional

Optional retry identity: the same id and body returns the same task. Not part of BytePlus's API.

at least 1 character; up to 128 characters

modelstring · required

The model.

dreamina-seedance-2-5-260628

contentarray · required

One text item with the prompt, then any media items: up to 30 images, 10 videos and 10 audio clips.

content[].typestring · required

What this item is.

text · image_url · video_url · audio_url

content[].textstring · optional

The prompt, on the text item.

up to 5,000 characters

content[].image_urlobject · optional

content[].image_url.urlstring · required

Public https URL of the image. The model provider fetches it.

up to 2,048 characters

content[].video_urlobject · optional

content[].video_url.urlstring · required

Public https URL of the video (MP4 or MOV). The model provider fetches it.

up to 2,048 characters

content[].audio_urlobject · optional

content[].audio_url.urlstring · required

Public https URL of the audio. The model provider fetches it.

up to 2,048 characters

content[].rolestring · optional

An image's role: first_frame (optionally with last_frame) makes those exact frames; reference_image guides a new shot. Videos are reference_video and audio reference_audio. A lone image without a role is the first frame.

first_frame · last_frame · reference_image · reference_video · reference_audio

ratiostring · optional

Frame shape. Defaults to 16:9, or adaptive (the input's shape) with a first frame or an edit or extension.

21:9 · 16:9 · 4:3 · 1:1 · 3:4 · 9:16 · adaptive

durationinteger · optional

Length in whole seconds, 4 to 30, or -1 for automatic. Defaults to 5 (automatic for an edit or extension).

minimum -1; maximum 30

resolutionstring · optional

Output resolution. Defaults to 720p.

480p · 720p · 1080p

generate_audioboolean · optional

Generate sound with the clip. Defaults to true.

watermarkboolean · optional

Add a watermark. Defaults to false.

seedinteger · optional

Seed for repeatable results; -1 for random.

minimum -1; maximum 4294967295

omni_reference_task_typestring · optional

With reference media: reference makes a new shot guided by them, edit changes the given video in place, extend continues it. Without it the model decides from the prompt.

reference · edit · extend

Example request

Terminal
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedance/contents/generations/tasks" \
  -H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "dreamina-seedance-2-5-260628",
  "content": [
    {
      "type": "text",
      "text": "A red kite over a beach at dusk, slow push-in"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/first-frame.jpg"
      },
      "role": "first_frame"
    }
  ],
  "resolution": "1080p",
  "duration": 6,
  "request_id": "kite-001"
}'

Response · 200

Example response
{
  "id": "0190e2c4-1b2c-4d3e-8f40-123456789abc",
  "model": "dreamina-seedance-2-5-260628",
  "status": "queued",
  "created_at": 1793361600,
  "updated_at": 1793361600,
  "resolution": "1080p",
  "ratio": "adaptive",
  "duration": 6,
  "framespersecond": 24,
  "generate_audio": true,
  "credits": {
    "price": null,
    "charged": null,
    "reserved": 4.89
  },
  "poll_after_seconds": 10
}
All response fields
idstring · required

The id returned when the task was created.

at least 1 character

modelstring · required

The model.

statusstring · required

queued, running, then succeeded or failed.

queued · running · succeeded · failed

contentobject · optional

content.video_urlstring · required

Absolute URL.

content.video_url_expires_atstring · required

ISO 8601 UTC timestamp.

usageobject · optional

usage.completion_tokensnumber · required

Output tokens the clip used: what its price is counted in.

usage.total_tokensnumber · required

The same count, as BytePlus reports it.

errorobject · optional

error.codestring · required

Stable failure code.

error.messagestring · required

Why it failed; a failed task is not charged.

created_atnumber · required

Unix seconds.

updated_atnumber · required

Unix seconds.

seednumber · optional

The seed asked for.

resolutionstring · required

Output resolution.

ratiostring · required

Frame shape.

durationnumber · required

Length asked for, or -1 for automatic.

framespersecondnumber · optional

Frames per second.

generate_audioboolean · optional

Whether sound was asked for.

creditsobject · required

credits.pricenumber | null · required

BytePlus's price for the clip, in credits (one per USD); null until it succeeds.

credits.chargednumber | null · required

Credits charged; null until the task ends.

credits.reservednumber · required

Credits held while the task runs.

poll_after_secondsnumber · optional

Present while queued or running: wait this long before checking again.

Errors

unauthorized, permission_denied, not_found, invalid_request, insufficient_credits, allowance_exhausted, cap_too_low, idempotency_conflict, rate_limited, internal_error, temporarily_unavailable.

GET

Check a Seedance video

GET /api/v1/seedance/contents/generations/tasks/{task_id}

Get a Seedance task in BytePlus's task shape: its status, and when it succeeded the clip's link, the tokens it used and its price in credits. While queued or running, wait poll_after_seconds before checking again.

Required permission: projects:read

Terminal states are succeeded and failed; a failed task's error says why, and it was not charged. content.video_url is a Ghostmotion link that expires after one hour: read the task again for a fresh one. It follows a redirect to temporary storage and needs no bearer header.

Path parameters

task_idstring · required

The id returned when the task was created.

at least 1 character

Query parameters

No query parameters required.

Example request

Terminal
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedance/contents/generations/tasks/$TASK_ID" \
  -H "Authorization: Bearer $GHOSTMOTION_API_KEY"

Response · 200

Example response
{
  "id": "0190e2c4-1b2c-4d3e-8f40-123456789abc",
  "model": "dreamina-seedance-2-5-260628",
  "status": "succeeded",
  "created_at": 1793361600,
  "updated_at": 1793361600,
  "resolution": "1080p",
  "ratio": "adaptive",
  "duration": 6,
  "framespersecond": 24,
  "generate_audio": true,
  "credits": {
    "price": 3.435413,
    "charged": 3.435413,
    "reserved": 0
  },
  "content": {
    "video_url": "https://app.ghostmotion.ai/api/v1/media/example-token",
    "video_url_expires_at": "2026-11-01T13:02:00.000Z"
  },
  "usage": {
    "completion_tokens": 293625,
    "total_tokens": 293625
  }
}
All response fields
idstring · required

The id returned when the task was created.

at least 1 character

modelstring · required

The model.

statusstring · required

queued, running, then succeeded or failed.

queued · running · succeeded · failed

contentobject · optional

content.video_urlstring · required

Absolute URL.

content.video_url_expires_atstring · required

ISO 8601 UTC timestamp.

usageobject · optional

usage.completion_tokensnumber · required

Output tokens the clip used: what its price is counted in.

usage.total_tokensnumber · required

The same count, as BytePlus reports it.

errorobject · optional

error.codestring · required

Stable failure code.

error.messagestring · required

Why it failed; a failed task is not charged.

created_atnumber · required

Unix seconds.

updated_atnumber · required

Unix seconds.

seednumber · optional

The seed asked for.

resolutionstring · required

Output resolution.

ratiostring · required

Frame shape.

durationnumber · required

Length asked for, or -1 for automatic.

framespersecondnumber · optional

Frames per second.

generate_audioboolean · optional

Whether sound was asked for.

creditsobject · required

credits.pricenumber | null · required

BytePlus's price for the clip, in credits (one per USD); null until it succeeds.

credits.chargednumber | null · required

Credits charged; null until the task ends.

credits.reservednumber · required

Credits held while the task runs.

poll_after_secondsnumber · optional

Present while queued or running: wait this long before checking again.

Errors

unauthorized, permission_denied, not_found, rate_limited, internal_error, temporarily_unavailable.