- Seedance Blog: AI Video Tutorials & Guides
- Seedance API Guide for Developers 2026: Integration, Endpoints & Best Practices
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.
- 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:
- Log in at seedance.tv
- Navigate to Settings → API
- Generate an API key
- 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: queued → processing → completed / 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.
Related Articles
More posts in the same locale you may want to read next.

Best Text to Video AI Tools 2026: Free Options That Actually Work
Discover the best text to video AI tools in 2026 for creators, marketers, startups, and agencies, with practical guidance on strengths, tradeoffs, and use cases.
Read article
50+ Best AI Video Prompts You Can Copy and Paste (2026)
Collection of 50+ tested AI video prompts for cinematic, nature, fantasy, product, and social media videos. Copy, paste, generate.
Read article
AI Video Generator for Real Estate: Create Property Videos Without a Camera (2026)
How AI video generators are transforming real estate marketing in 2026. Learn workflows, tools, and strategies to create professional property videos using Seedance, Veo 3, and more.
Read article