Seedance API Guide for Developers 2026: Integration, Endpoints & Best Practices

E
Emma Chen·6 min read·Apr 20, 2026
Share on X
Seedance API Guide for Developers 2026: Integration, Endpoints & Best Practices

Seedance API Guide for Developers 2026: Integration, Endpoints & Best Practices

Building applications with AI video generation requires reliable API access, clear documentation, and predictable pricing. This guide covers everything developers need to know about integrating Seedance into their applications — from authentication and endpoints to rate limits, error handling, and production best practices.

What Is the Seedance API?

The Seedance API provides programmatic access to Seedance's AI video generation capabilities. Developers can integrate Seedance into web applications, mobile apps, backend services, and automated workflows through a RESTful API that accepts text or image inputs and returns generated video content.

The API supports the same core functionality as the web interface:

Ready to try it yourself?

Free credits on signup. Plans from $20/month.

Try Seedance free
  • Text-to-video: Generate video from text prompts
  • Image-to-video: Animate a static image into a video
  • Style control: Apply visual style parameters via prompt
  • Resolution options: 720p and 1080p output

Getting Started: Authentication

API Key Setup

Access the Seedance API through your account dashboard:

  1. Log in at seedance.tv
  2. Navigate to Settings → API
  3. Generate an API key
  4. Store the key securely — it grants full access to your account

Never expose your API key in client-side code. Always make API calls from your backend server.

Authentication Headers

All API requests must include your API key in the authorization header:

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Core Endpoints

Text-to-Video Generation

POST /api/v1/generate/text-to-video

Request body:

{
  "prompt": "Aerial view of a mountain range at golden hour, slow drone shot, cinematic",
  "duration": 8,
  "resolution": "1080p",
  "aspect_ratio": "16:9",
  "style": "cinematic"
}

Response:

{
  "job_id": "job_abc123",
  "status": "queued",
  "estimated_completion": "2026-04-20T10:00:30Z",
  "credits_used": 10
}

Video generation is asynchronous. The response includes a job_id to poll for completion.

Image-to-Video Generation

POST /api/v1/generate/image-to-video

Request body:

{
  "image_url": "https://your-storage.com/source-image.jpg",
  "prompt": "Camera slowly pulls back to reveal the full scene",
  "duration": 6,
  "resolution": "1080p",
  "motion_intensity": 0.7
}

Alternatively, upload the image directly:

{
  "image_base64": "BASE64_ENCODED_IMAGE_DATA",
  "prompt": "...",
  "duration": 6
}

Job Status Check

GET /api/v1/jobs/{job_id}

Response:

{
  "job_id": "job_abc123",
  "status": "completed",
  "created_at": "2026-04-20T10:00:00Z",
  "completed_at": "2026-04-20T10:00:45Z",
  "output": {
    "video_url": "https://cdn.seedance.tv/output/job_abc123.mp4",
    "thumbnail_url": "https://cdn.seedance.tv/output/job_abc123_thumb.jpg",
    "duration": 8,
    "resolution": "1080p",
    "file_size_mb": 24.5
  }
}

Status values: queuedprocessingcompleted / failed

List Jobs

GET /api/v1/jobs?limit=20&offset=0&status=completed

Returns paginated list of generation jobs for your account.

Error Handling

Standard Error Response Format

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "API rate limit exceeded. Retry after 60 seconds.",
    "retry_after": 60
  }
}

Common Error Codes

Code HTTP Status Description
INVALID_API_KEY 401 API key missing or invalid
INSUFFICIENT_CREDITS 402 Account has no remaining credits
RATE_LIMIT_EXCEEDED 429 Too many requests — back off and retry
INVALID_PROMPT 400 Prompt violates content policy
INVALID_IMAGE 400 Image format not supported or corrupt
JOB_FAILED 500 Generation failed — retry with same parameters
SERVICE_UNAVAILABLE 503 Temporary service issue — retry with backoff

Retry Strategy

Implement exponential backoff for retryable errors:

import time
import requests

def generate_with_retry(prompt: str, max_retries: int = 3) -> dict:
    base_delay = 1.0
    for attempt in range(max_retries):
        try:
            response = requests.post(
                'https://api.seedance.tv/v1/generate/text-to-video',
                headers={'Authorization': f'Bearer {API_KEY}'},
                json={'prompt': prompt, 'duration': 8}
            )
            if response.status_code == 429:
                retry_after = response.json().get('error', {}).get('retry_after', 60)
                time.sleep(retry_after)
                continue
            if response.status_code >= 500:
                delay = base_delay * (2 ** attempt)
                time.sleep(delay)
                continue
            response.raise_for_status()
            return response.json()
        except requests.RequestException as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(base_delay * (2 ** attempt))
    raise Exception("Max retries exceeded")

Polling for Job Completion

Generation typically takes 30-90 seconds. Implement efficient polling:

import time
import requests

def wait_for_completion(job_id: str, timeout: int = 300) -> dict:
    """Poll job status until complete or timeout."""
    start_time = time.time()
    poll_interval = 5  # Start with 5-second intervals
    
    while time.time() - start_time < timeout:
        response = requests.get(
            f'https://api.seedance.tv/v1/jobs/{job_id}',
            headers={'Authorization': f'Bearer {API_KEY}'}
        )
        job = response.json()
        
        if job['status'] == 'completed':
            return job['output']
        elif job['status'] == 'failed':
            raise Exception(f"Job {job_id} failed")
        
        # Back off polling interval over time
        poll_interval = min(poll_interval * 1.5, 30)
        time.sleep(poll_interval)
    
    raise TimeoutError(f"Job {job_id} timed out after {timeout} seconds")

Rate Limits

Free Tier Rate Limits

Limit Value
Requests per minute 10
Concurrent jobs 2
Daily generations Unlimited
Max video duration 8 seconds

Production Rate Limits

Higher rate limits available for production applications. Contact Seedance support for enterprise rate limit increases.

Rate Limit Headers

API responses include rate limit information in headers:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1745123456

Complete Python SDK Example

import time
import requests
from typing import Optional

class SeedanceClient:
    BASE_URL = "https://api.seedance.tv/v1"
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        })
    
    def generate_text_to_video(
        self,
        prompt: str,
        duration: int = 8,
        resolution: str = "1080p",
        aspect_ratio: str = "16:9"
    ) -> str:
        """Submit a text-to-video generation job. Returns job_id."""
        response = self.session.post(
            f"{self.BASE_URL}/generate/text-to-video",
            json={
                "prompt": prompt,
                "duration": duration,
                "resolution": resolution,
                "aspect_ratio": aspect_ratio
            }
        )
        response.raise_for_status()
        return response.json()['job_id']
    
    def generate_image_to_video(
        self,
        image_url: str,
        prompt: str,
        duration: int = 6,
        motion_intensity: float = 0.5
    ) -> str:
        """Submit an image-to-video generation job. Returns job_id."""
        response = self.session.post(
            f"{self.BASE_URL}/generate/image-to-video",
            json={
                "image_url": image_url,
                "prompt": prompt,
                "duration": duration,
                "motion_intensity": motion_intensity
            }
        )
        response.raise_for_status()
        return response.json()['job_id']
    
    def wait_for_job(self, job_id: str, timeout: int = 300) -> dict:
        """Poll until job completes. Returns output dict."""
        start = time.time()
        interval = 5
        
        while time.time() - start < timeout:
            response = self.session.get(f"{self.BASE_URL}/jobs/{job_id}")
            response.raise_for_status()
            job = response.json()
            
            if job['status'] == 'completed':
                return job['output']
            elif job['status'] == 'failed':
                raise Exception(f"Job failed: {job_id}")
            
            interval = min(interval * 1.2, 20)
            time.sleep(interval)
        
        raise TimeoutError(f"Job timeout: {job_id}")
    
    def create_video(
        self,
        prompt: str,
        duration: int = 8,
        resolution: str = "1080p"
    ) -> dict:
        """End-to-end: submit job, wait for completion, return output."""
        job_id = self.generate_text_to_video(prompt, duration, resolution)
        return self.wait_for_job(job_id)


# Usage example
client = SeedanceClient(api_key="your_api_key_here")

output = client.create_video(
    prompt="Luxury watch on marble surface, dramatic lighting, slow rotation, cinematic",
    duration=8,
    resolution="1080p"
)

print(f"Video URL: {output['video_url']}")
print(f"Duration: {output['duration']}s")
print(f"File size: {output['file_size_mb']}MB")

Node.js / TypeScript Example

interface GenerateOptions {
  prompt: string;
  duration?: number;
  resolution?: '720p' | '1080p';
  aspectRatio?: '16:9' | '9:16' | '1:1';
}

interface JobOutput {
  videoUrl: string;
  thumbnailUrl: string;
  duration: number;
  fileSizeMb: number;
}

class SeedanceClient {
  private baseUrl = 'https://api.seedance.tv/v1';
  private headers: Record<string, string>;

  constructor(apiKey: string) {
    this.headers = {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    };
  }

  async generateVideo(options: GenerateOptions): Promise<string> {
    const response = await fetch(`${this.baseUrl}/generate/text-to-video`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        prompt: options.prompt,
        duration: options.duration ?? 8,
        resolution: options.resolution ?? '1080p',
        aspect_ratio: options.aspectRatio ?? '16:9',
      }),
    });
    const data = await response.json();
    return data.job_id;
  }

  async waitForJob(jobId: string, timeoutMs = 300_000): Promise<JobOutput> {
    const start = Date.now();
    let interval = 5000;

    while (Date.now() - start < timeoutMs) {
      const response = await fetch(`${this.baseUrl}/jobs/${jobId}`, {
        headers: this.headers,
      });
      const job = await response.json();

      if (job.status === 'completed') return job.output;
      if (job.status === 'failed') throw new Error(`Job failed: ${jobId}`);

      interval = Math.min(interval * 1.2, 20000);
      await new Promise(r => setTimeout(r, interval));
    }
    throw new Error(`Job timeout: ${jobId}`);
  }

  async createVideo(options: GenerateOptions): Promise<JobOutput> {
    const jobId = await this.generateVideo(options);
    return this.waitForJob(jobId);
  }
}

// Usage
const client = new SeedanceClient(process.env.SEEDANCE_API_KEY!);
const output = await client.createVideo({
  prompt: 'Mountain sunrise, slow aerial drone, cinematic, golden hour',
  duration: 8,
  resolution: '1080p',
});
console.log('Video ready:', output.videoUrl);

Webhook Integration (Async Notification)

Instead of polling, register a webhook URL to receive completion notifications:

POST /api/v1/webhooks

{
  "url": "https://your-app.com/webhooks/seedance",
  "events": ["job.completed", "job.failed"],
  "secret": "your_webhook_secret"
}

Webhook payload (sent to your endpoint on completion):

{
  "event": "job.completed",
  "job_id": "job_abc123",
  "timestamp": "2026-04-20T10:01:15Z",
  "output": {
    "video_url": "https://cdn.seedance.tv/output/job_abc123.mp4",
    "duration": 8,
    "resolution": "1080p"
  }
}

Verify webhook signatures to prevent spoofing:

import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

Production Best Practices

1. Store API Keys Securely

# Use environment variables
import os
api_key = os.environ.get('SEEDANCE_API_KEY')
if not api_key:
    raise ValueError("SEEDANCE_API_KEY environment variable not set")

2. Implement Request Queuing

For high-volume applications, implement a queue to respect rate limits:

from queue import Queue
import threading

class VideoGenerationQueue:
    def __init__(self, client: SeedanceClient, max_concurrent: int = 2):
        self.client = client
        self.queue = Queue()
        self.semaphore = threading.Semaphore(max_concurrent)
    
    def submit(self, prompt: str) -> str:
        """Add a generation job to the queue. Returns job_id."""
        with self.semaphore:
            job_id = self.client.generate_text_to_video(prompt)
            return job_id

3. Cache Generated Videos

Avoid regenerating identical content:

import hashlib
import json
from functools import lru_cache

def get_cache_key(prompt: str, duration: int, resolution: str) -> str:
    params = json.dumps({'prompt': prompt, 'duration': duration, 'resolution': resolution}, sort_keys=True)
    return hashlib.sha256(params.encode()).hexdigest()

# Check cache before generating
cache_key = get_cache_key(prompt, duration, resolution)
if cached_url := video_cache.get(cache_key):
    return cached_url

# Generate and cache
output = client.create_video(prompt=prompt, duration=duration)
video_cache.set(cache_key, output['video_url'], ttl=86400)
return output['video_url']

4. Handle Concurrent Users

For applications with multiple users generating videos simultaneously:

import asyncio
import aiohttp

async def generate_videos_concurrent(prompts: list[str]) -> list[dict]:
    """Generate multiple videos concurrently with rate limiting."""
    semaphore = asyncio.Semaphore(5)  # Max 5 concurrent jobs
    
    async def generate_one(prompt: str) -> dict:
        async with semaphore:
            # Submit job
            job_id = await submit_job_async(prompt)
            # Wait for completion
            return await wait_for_job_async(job_id)
    
    return await asyncio.gather(*[generate_one(p) for p in prompts])

Frequently Asked Questions

Is there a free tier for the Seedance API? Yes. Seedance offers API access on the free tier with rate limits. For production applications requiring higher throughput, contact Seedance about production API plans.

What video formats does the API return? The API returns MP4 files with H.264 encoding by default. The output URL is a direct download link valid for 24 hours.

How long are generated videos available? Output video URLs are available for download for 24 hours. Download and store videos to your own storage for permanent access.

Can I use API-generated videos commercially? Yes. Seedance's free tier includes commercial use rights. Videos generated via API are subject to the same commercial license as web-generated content.

What's the maximum video duration via API? 8 seconds per generation on the standard tier. Contact Seedance for extended duration options.

How do I handle errors in production? Implement retry with exponential backoff for 429 and 5xx errors. Log all failures with job_id for debugging. Set up alerts for elevated error rates.

Start building with Seedance at seedance.tv →

Advanced Integration Patterns

Batch Video Generation Pipeline

For content teams that need to generate many videos regularly, a batch pipeline is more efficient than individual requests:

import csv
import time
from pathlib import Path
from dataclasses import dataclass

@dataclass
class VideoJob:
    id: str
    prompt: str
    output_filename: str
    status: str = "pending"
    video_url: str = ""

def batch_generate_from_csv(input_csv: str, output_dir: str) -> None:
    """Read prompts from CSV, generate videos, save results."""
    client = SeedanceClient(api_key=os.environ['SEEDANCE_API_KEY'])
    jobs = []
    
    # Read prompts
    with open(input_csv) as f:
        reader = csv.DictReader(f)
        for row in reader:
            jobs.append(VideoJob(
                id=row['id'],
                prompt=row['prompt'],
                output_filename=row.get('filename', f"video_{row['id']}.mp4")
            ))
    
    # Submit all jobs
    pending_jobs = {}
    for job in jobs:
        try:
            job_id = client.generate_text_to_video(job.prompt)
            pending_jobs[job_id] = job
            job.status = "submitted"
            print(f"Submitted: {job.id}{job_id}")
            time.sleep(0.1)  # Rate limit buffer
        except Exception as e:
            job.status = "submission_failed"
            print(f"Failed to submit {job.id}: {e}")
    
    # Poll all pending jobs
    while pending_jobs:
        completed = []
        for api_job_id, job in pending_jobs.items():
            try:
                output = client.check_job(api_job_id)
                if output['status'] == 'completed':
                    job.video_url = output['output']['video_url']
                    job.status = "completed"
                    completed.append(api_job_id)
                    print(f"Completed: {job.id}")
                elif output['status'] == 'failed':
                    job.status = "failed"
                    completed.append(api_job_id)
            except Exception as e:
                print(f"Error checking {api_job_id}: {e}")
        
        for job_id in completed:
            del pending_jobs[job_id]
        
        if pending_jobs:
            time.sleep(10)
    
    # Save results
    results_file = Path(output_dir) / "results.csv"
    with open(results_file, 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['id', 'status', 'video_url', 'filename'])
        writer.writeheader()
        for job in jobs:
            writer.writerow({
                'id': job.id,
                'status': job.status,
                'video_url': job.video_url,
                'filename': job.output_filename
            })
    
    print(f"Results saved to {results_file}")
    successful = sum(1 for j in jobs if j.status == 'completed')
    print(f"Completed: {successful}/{len(jobs)}")

Integration with Content Management Systems

For teams using CMS platforms, integrate Seedance into your content pipeline:

# Example: WordPress integration via REST API
import requests

def publish_post_with_video(
    wp_url: str,
    wp_credentials: tuple,
    title: str,
    content: str,
    video_prompt: str
) -> dict:
    """Generate a video and publish it alongside a WordPress post."""
    
    # Generate video
    seedance = SeedanceClient(api_key=os.environ['SEEDANCE_API_KEY'])
    output = seedance.create_video(prompt=video_prompt)
    video_url = output['video_url']
    
    # Embed video in post content
    video_embed = f'<video controls src="{video_url}" style="max-width:100%"></video>'
    full_content = f"{video_embed}\n\n{content}"
    
    # Publish to WordPress
    response = requests.post(
        f"{wp_url}/wp-json/wp/v2/posts",
        auth=wp_credentials,
        json={
            "title": title,
            "content": full_content,
            "status": "publish"
        }
    )
    return response.json()

Serverless Integration (AWS Lambda / Vercel)

For serverless architectures, use asynchronous processing:

# AWS Lambda handler
import json
import boto3

def lambda_handler(event, context):
    """Lambda function triggered by SQS message with video generation request."""
    body = json.loads(event['Records'][0]['body'])
    
    client = SeedanceClient(api_key=os.environ['SEEDANCE_API_KEY'])
    
    try:
        job_id = client.generate_text_to_video(
            prompt=body['prompt'],
            duration=body.get('duration', 8)
        )
        
        # Store job_id for async completion tracking
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table('VideoJobs')
        table.put_item(Item={
            'job_id': job_id,
            'request_id': body['request_id'],
            'status': 'processing',
            'created_at': int(time.time())
        })
        
        return {'statusCode': 200, 'body': json.dumps({'job_id': job_id})}
    
    except Exception as e:
        return {'statusCode': 500, 'body': json.dumps({'error': str(e)})}

Monitoring and Observability

For production applications, implement comprehensive monitoring:

import logging
from datetime import datetime

# Configure structured logging
logging.basicConfig(
    format='%(asctime)s %(levelname)s %(name)s %(message)s',
    level=logging.INFO
)
logger = logging.getLogger('seedance.api')

class MonitoredSeedanceClient(SeedanceClient):
    def create_video(self, **kwargs) -> dict:
        start = datetime.now()
        try:
            result = super().create_video(**kwargs)
            duration_ms = (datetime.now() - start).total_seconds() * 1000
            logger.info("video_generated", extra={
                'prompt_length': len(kwargs.get('prompt', '')),
                'duration_ms': duration_ms,
                'resolution': kwargs.get('resolution', '1080p')
            })
            return result
        except Exception as e:
            logger.error("video_generation_failed", extra={
                'error': str(e),
                'prompt': kwargs.get('prompt', '')[:100]
            })
            raise

Track these key metrics in production:

  • Generation latency: P50, P95, P99 completion times
  • Error rates: By error code, with alerting thresholds
  • Credit consumption: Daily usage vs. budget
  • Queue depth: Number of pending jobs at any time
  • Success rate: Percentage of jobs completing successfully

The Seedance API is designed for developers who want to bring professional AI video generation into their applications. With straightforward authentication, clear error codes, and flexible integration patterns, you can add AI video generation to any application in a single development sprint.

Start building with Seedance's free API at seedance.tv →

Building production-quality applications with AI video generation requires attention to the same engineering fundamentals as any API integration: secure credential management, robust error handling, efficient polling or webhook patterns, and comprehensive observability. Seedance provides a developer-friendly API that makes these integrations straightforward. Whether you are building a content automation pipeline, a user-facing video creation tool, or an internal production workflow, the patterns in this guide provide the foundation for reliable, scalable Seedance API integration.

The combination of unlimited free generations, commercial rights, and a clean API makes Seedance uniquely accessible among AI video platforms. You can prototype, test, and launch a production application without incurring API costs — a significant advantage compared to usage-based pricing models that make cost unpredictable during development. Start with the free tier, build your integration, measure your usage patterns, and scale confidently knowing the platform supports your growth.

For teams evaluating AI video APIs, the decision often comes down to three factors: quality, cost, and developer experience. Seedance delivers on all three — professional-quality video output, a free tier with no watermarks and commercial rights, and a clean RESTful API with predictable behavior. The monitoring and integration patterns described in this guide ensure that your Seedance integration will be maintainable and observable as your application grows in complexity and scale. The Seedance API is developer-friendly by design — clear authentication, predictable error codes, and flexible integration patterns that work with any technology stack. The investment in a solid integration is typically a single sprint, and the return is unlimited AI video generation capacity integrated directly into your application or workflow. Start building with the free API today at seedance.tv to experience firsthand how AI video generation can transform your application or workflow.

Ready to try it yourself?

Put the steps from this guide into practice with Seedance and turn prompts or images into polished videos in minutes.

Free credits on signup. Plans from $20/month.