Developer API

Build on seedancee2.ai.

Built on the underlying Seedance 2.0 model, we unify and encapsulate upstream provider capabilities, then expose them through a standardized public API.

Stable API contract

Integrate once with `pro`, `fast`, and `mini` while we keep upstream provider changes behind the same public contract.

Text and image workflows

Run prompt-first and image-first video generation through one API surface, without exposing upstream provider-specific differences to customers.

Async jobs, polling, webhooks

Submit a generation request, poll job status, or receive a webhook when the video is ready with a clean Seedancee2 response shape.

Seedancee2 Enterprise API

Built on the underlying Seedance 2.0 model, Seedancee2 unifies and encapsulates upstream provider capabilities, then exposes them through a standardized public API.

Base URL

https://api.seedancee2.ai

Quickstart

  1. Get an API key from the Seedancee2 team.
  2. Create a video generation task.
  3. Poll the task or receive a webhook when it completes.

Minimal curl example:

curl -X POST "https://api.seedancee2.ai/v1/videos/generations" \
  -H "Authorization: Bearer sk_seedancee2_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mini",
    "input": {
      "prompt": "A cinematic drone shot of waves breaking against black volcanic rocks",
      "duration": 5,
      "resolution": "720p",
      "aspect_ratio": "16:9"
    },
    "metadata": {
      "customer_job_id": "job_123"
    }
  }'

Minimal JavaScript example:

const response = await fetch("https://api.seedancee2.ai/v1/videos/generations", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk_seedancee2_live_xxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "mini",
    input: {
      prompt: "A cinematic drone shot of waves breaking against black volcanic rocks",
      duration: 5,
      resolution: "720p",
      aspect_ratio: "16:9",
    },
    metadata: {
      customer_job_id: "job_123",
    },
  }),
});

const result = await response.json();
console.log(result);

Minimal Python example:

import requests

response = requests.post(
    "https://api.seedancee2.ai/v1/videos/generations",
    headers={
        "Authorization": "Bearer sk_seedancee2_live_xxxxx",
        "Content-Type": "application/json",
    },
    json={
        "model": "mini",
        "input": {
            "prompt": "A cinematic drone shot of waves breaking against black volcanic rocks",
            "duration": 5,
            "resolution": "720p",
            "aspect_ratio": "16:9",
        },
        "metadata": {
            "customer_job_id": "job_123",
        },
    },
    timeout=60,
)

print(response.json())

Authentication

All requests use bearer token authentication.

Authorization: Bearer sk_seedancee2_live_xxxxx
Content-Type: application/json

You can also send the key in x-api-key, but Authorization: Bearer ... is recommended.

API keys and model access

  • Your Seedancee2 API key is issued by the Seedancee2 team, from your profile, or from the enterprise admin flow.
  • The same Seedancee2 API key works across public models: pro, fast, and mini.
  • You do not need separate customer-facing API keys for Mini, Fast, or Pro.
  • Upstream provider credentials are managed by Seedancee2 and are never required in customer requests.

If you already have a working Seedancee2 API key, switching models only requires changing the request model field. Example:

{
  "model": "mini"
}

to:

{
  "model": "fast"
}

or:

{
  "model": "pro"
}

Public Models

These are the public model names your integration should use.

ModelPositioningDurationResolution
proStandard quality production generation4-15s480p, 720p, 1080p
fastFaster iteration and preview workflows4-15s480p, 720p
miniLower-cost generation4-15s480p, 720p

New integrations should use pro, fast, and mini.

Supported aspect ratios:

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

Credits

Public API credits follow the same deduction rules visible in the Seedancee2 product.

Formula:

credits = duration_seconds * per_second_rate * number_of_outputs

Reference images, videos, and audio currently do not add extra customer-facing surcharges. The reserved and charged credit values in the API response are the source of truth for each task.

Per-second rates currently aligned with the live Seedancee2 product billing rules:

Model480p720p1080p
pro10 credits/s20 credits/s50 credits/s
fast8 credits/s16 credits/sNot supported
mini5 credits/s10 credits/sNot supported

Examples:

ScenarioCredits
mini, 5s, 720p50
pro, 4s, 480p40
fast, 10s, 720p160
pro, 5s, 720p, 2 reference images100

If a task fails and the job is eligible for refund, the returned status payload will show the refunded credits.

Task Lifecycle

Task statuses returned by the public API:

StatusMeaning
pendingAccepted and waiting to start
processingRunning
completedFinished successfully
failedFinished without usable output

Create Video Task

POST /v1/videos/generations

Top-level request fields:

FieldTypeRequiredDescription
modelstringYesPublic model name: pro, fast, or mini
inputobjectYesGeneration parameters
callback_urlstringNoPublic webhook URL for completion or failure callbacks
metadataobjectNoCustomer-defined metadata echoed back in polling and webhook responses

Input fields:

FieldTypeRequiredDescription
promptstringYesText prompt
generation_typestringNoomni_reference or first_and_last_frames; default omni_reference
image_urlsstring[]NoReference image URLs
video_urlstringNoSingle reference video URL
video_urlsstring[]NoReference video URLs. Do not send together with video_url
audio_urlsstring[]NoReference audio URLs
start_image_urlstringNoFirst frame image for first_and_last_frames
end_image_urlstringNoLast frame image for first_and_last_frames
durationintegerNoOutput duration in seconds, 4-15; default 5
resolutionstringNo480p, 720p, or 1080p; available resolutions depend on the selected model
aspect_ratiostringNo16:9, 4:3, 1:1, 3:4, 9:16, 21:9, or adaptive
generate_audiobooleanNoGenerate synchronized audio when supported
watermarkbooleanNoRequest watermarked output
seedintegerNoDeterministic seed
return_last_framebooleanNoInclude the last frame image in the output payload

Full example:

curl -X POST "https://api.seedancee2.ai/v1/videos/generations" \
  -H "Authorization: Bearer sk_seedancee2_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "pro",
    "callback_url": "https://example.com/webhooks/seedancee2",
    "input": {
      "prompt": "A cinematic tracking shot through a rain-soaked neon market at night",
      "image_urls": [
        "https://example-cdn.com/reference-1.png",
        "https://example-cdn.com/reference-2.png"
      ],
      "duration": 5,
      "resolution": "720p",
      "aspect_ratio": "16:9",
      "generate_audio": true,
      "return_last_frame": true
    },
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }'

Success response:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "pending",
    "model": "pro",
    "credits_reserved": 100,
    "created_at": "2026-06-29T10:00:00.000Z"
  }
}

Get Video Task

GET /v1/videos/generations/{id}

Polling example:

const response = await fetch(
  "https://api.seedancee2.ai/v1/videos/generations/vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
  {
    headers: {
      Authorization: "Bearer sk_seedancee2_live_xxxxx",
    },
  }
);

const result = await response.json();
console.log(result);

Processing response:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "processing",
    "model": "pro",
    "created_at": "2026-06-29T10:00:00.000Z",
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }
}

Completed response:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "completed",
    "model": "pro",
    "created_at": "2026-06-29T10:00:00.000Z",
    "completed_at": "2026-06-29T10:06:20.000Z",
    "credits_charged": 100,
    "output": {
      "video_url": "https://media.seedancee2.ai/videos/2026/06/29/vid_01jz8b7q4x8k2p9w3m5c6n7r8s.mp4",
      "thumbnail_url": "https://media.seedancee2.ai/video-posters/2026/06/29/vid_01jz8b7q4x8k2p9w3m5c6n7r8s.jpg",
      "last_frame_url": "https://media.seedancee2.ai/video-posters/2026/06/29/vid_01jz8b7q4x8k2p9w3m5c6n7r8s.jpg"
    },
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }
}

Failed response:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "failed",
    "model": "pro",
    "created_at": "2026-06-29T10:00:00.000Z",
    "credits_charged": 0,
    "credits_refunded": 100,
    "error": {
      "code": "generation_failed",
      "message": "The video could not be generated. Please try again with a different prompt.",
      "type": "generation_error"
    },
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }
}

List Video Tasks

GET /v1/videos/generations

Supported query parameters:

FieldTypeDescription
statusstringFilter by pending, processing, completed, or failed
limitintegerMax results. Default 20, max 100

Example:

curl "https://api.seedancee2.ai/v1/videos/generations?status=completed&limit=10" \
  -H "Authorization: Bearer sk_seedancee2_live_xxxxx"

List Models

GET /v1/models

Example response:

{
  "data": [
    {
      "id": "pro",
      "status": "active",
      "resolutions": ["480p", "720p", "1080p"],
      "duration": {
        "min": 4,
        "max": 15
      }
    }
  ]
}

Usage Summary

GET /v1/usage

Supported query parameters:

FieldTypeDescription
startstringOptional ISO 8601 start datetime filter
endstringOptional ISO 8601 end datetime filter
limitintegerMax daily timeline rows to return. Default 30, max 365

Example:

curl "https://api.seedancee2.ai/v1/usage?start=2026-07-01T00:00:00.000Z&end=2026-07-31T23:59:59.999Z&limit=7" \
  -H "Authorization: Bearer sk_seedancee2_live_xxxxx"

Example response:

{
  "data": {
    "range": {
      "start": "2026-07-01T00:00:00.000Z",
      "end": "2026-07-31T23:59:59.999Z"
    },
    "summary": {
      "total_jobs": 12,
      "pending_jobs": 1,
      "processing_jobs": 2,
      "completed_jobs": 8,
      "failed_jobs": 1,
      "credits_charged": 280,
      "credits_refunded": 40,
      "net_credits": 240
    },
    "by_model": [
      {
        "model": "mini",
        "total_jobs": 7,
        "pending_jobs": 0,
        "processing_jobs": 1,
        "completed_jobs": 5,
        "failed_jobs": 1,
        "credits_charged": 120,
        "credits_refunded": 20,
        "net_credits": 100
      },
      {
        "model": "pro",
        "total_jobs": 5,
        "pending_jobs": 1,
        "processing_jobs": 1,
        "completed_jobs": 3,
        "failed_jobs": 0,
        "credits_charged": 160,
        "credits_refunded": 20,
        "net_credits": 140
      }
    ],
    "timeline": [
      {
        "date": "2026-07-01",
        "total_jobs": 4,
        "pending_jobs": 0,
        "processing_jobs": 1,
        "completed_jobs": 3,
        "failed_jobs": 0,
        "credits_charged": 100,
        "credits_refunded": 0,
        "net_credits": 100
      }
    ]
  }
}

Webhooks

If callback_url is provided, Seedancee2 sends a POST request when the task reaches completed or failed.

Recommended headers to inspect:

X-Seedancee2-Event: video.generation.completed
X-Seedancee2-Signature: t=1770000000,v1=...

If webhook signing is enabled for your account, the body is signed as:

payload_to_sign = "{timestamp}.{raw_json_body}"
signature = hex(hmac_sha256(webhook_secret, payload_to_sign))

Completed webhook payload:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "completed",
    "model": "pro",
    "created_at": "2026-06-29T10:00:00.000Z",
    "completed_at": "2026-06-29T10:06:20.000Z",
    "credits_charged": 100,
    "output": {
      "video_url": "https://media.seedancee2.ai/videos/2026/06/29/vid_01jz8b7q4x8k2p9w3m5c6n7r8s.mp4",
      "thumbnail_url": "https://media.seedancee2.ai/video-posters/2026/06/29/vid_01jz8b7q4x8k2p9w3m5c6n7r8s.jpg"
    },
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }
}

Failed webhook payload:

{
  "data": {
    "id": "vid_01jz8b7q4x8k2p9w3m5c6n7r8s",
    "status": "failed",
    "model": "pro",
    "created_at": "2026-06-29T10:00:00.000Z",
    "credits_charged": 0,
    "credits_refunded": 100,
    "error": {
      "code": "generation_failed",
      "message": "The video could not be generated. Please try again with a different prompt.",
      "type": "generation_error"
    },
    "metadata": {
      "customer_job_id": "job_123",
      "campaign": "launch_week"
    }
  }
}

Input Guidelines

Images:

RequirementValue
FormatsJPEG, PNG, WebP, BMP, TIFF, GIF
CountUp to 9 reference images
first_and_last_framesExactly 2 images

Videos:

RequirementValue
video_url1
video_urlsUp to 3

Audio:

RequirementValue
audio_urlsUp to 3

Errors

Error format:

{
  "error": {
    "code": "insufficient_credits",
    "message": "Your credit balance is too low. Please top up.",
    "type": "billing_error"
  }
}

Current public error codes:

HTTP statusCodeTypeDescription
400invalid_requestinvalid_request_errorMissing or invalid parameters
401invalid_api_keyauthentication_errorAPI key is missing, invalid, or disabled
402insufficient_creditsbilling_errorCredit balance too low
404model_not_foundinvalid_request_errorModel does not exist or is inactive
404task_not_foundinvalid_request_errorTask ID does not exist
500internal_errorapi_errorUnexpected server error

Integration Notes

  • Use only public model names such as pro, fast, and mini.
  • Do not build logic against internal provider names, internal task IDs, or internal media hosts.
  • Store your own metadata so you can join callbacks and polling results to internal business records.
  • For production use, prefer webhooks for completion and keep polling as a fallback.