sedance.appOpen studio

API

One credit balance powers the studio and the API — the same ledger, the same prices, two front doors. Keys are issued from your dashboard, shown once, and stored only as a hash.

Authentication

Authorization: Bearer sk_live_...

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. A 429 also carries Retry-After.

Create a generation

Returns 202 immediately with the credits held and an ETA. Generation is asynchronous: poll the job, or cancel it. Pass an Idempotency-Key and a retried request will never produce a second billed job.

curl https://sedance.app/api/v1/generations \
  -H "Authorization: Bearer $SEDANCE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5",
    "prompt": "One continuous take through a night market, camera rising over the stalls",
    "resolution": "1080p",
    "duration_sec": 30,
    "aspect_ratio": "16:9",
    "confirm_cost": true
  }'

{ "id": "gen_...", "status": "reserved", "credits_held": 7179, "eta_seconds": 210 }

confirm_cost is required for jobs above the model’s confirmation threshold. Without it the call returns 400 confirmation_required and the exact price, so a client can prompt before spending.

Poll it

Match your poll interval to the job. A 30-second generation should start at 10s intervals, not 3s — polling a long job aggressively wastes quota and can trip provider rate limits.

curl https://sedance.app/api/v1/generations/gen_... \
  -H "Authorization: Bearer $SEDANCE_API_KEY"

{
  "id": "gen_...",
  "status": "succeeded",
  "output_url": "https://cdn.sedance.app/generations/gen_.../output.mp4",
  "credits_charged": 7179,
  "latency_ms": 214300
}

Python

import os, time, requests

API = "https://sedance.app/api/v1"
headers = {"Authorization": f"Bearer {os.environ['SEDANCE_API_KEY']}"}

job = requests.post(f"{API}/generations", headers=headers, json={
    "model": "seedance-2.5",
    "prompt": "One continuous take through a night market",
    "resolution": "1080p",
    "duration_sec": 30,
    "confirm_cost": True,
}).json()

while True:
    time.sleep(10)
    state = requests.get(f"{API}/generations/{job['id']}", headers=headers).json()
    if state["status"] in ("succeeded", "failed", "rejected", "expired"):
        break

print(state.get("output_url") or state["error"])

TypeScript

const api = "https://sedance.app/api/v1";
const headers = {
  Authorization: `Bearer ${process.env.SEDANCE_API_KEY}`,
  "Content-Type": "application/json",
};

const created = await fetch(`${api}/generations`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({
    model: "seedance-2.5",
    prompt: "One continuous take through a night market",
    resolution: "1080p",
    duration_sec: 30,
    confirm_cost: true,
  }),
}).then((r) => r.json());

let job = created;
while (!["succeeded", "failed", "rejected", "expired"].includes(job.status)) {
  await new Promise((r) => setTimeout(r, 10_000));
  job = await fetch(`${api}/generations/${created.id}`, { headers }).then((r) => r.json());
}

Other endpoints

  • GET /api/v1/generations — paginated list of your jobs.
  • DELETE /api/v1/generations/:id — cancel a job that has not finished. Refunds in full.
  • GET /api/v1/models — the registry: capabilities, plan gates, latency, and credit rates per resolution. Unverified vendor claims are listed separately, so you can decide what to trust.
  • GET /api/v1/credits — balance, its breakdown, plan limits and today’s spend against the daily ceiling.

Errors

Always the same shape: { error: { type, code, message, docs_url } }. Switch on code — it is stable.

400parameter_invalidThe request does not match the model’s capabilities. Nothing is charged.
400confirmation_requiredCost is above the confirmation threshold. Resend with confirm_cost: true.
401unauthorizedMissing or invalid API key.
402insufficient_creditsBalance is short. The shortfall is in error.meta.
403duration_requires_upgradeThe plan does not cover this duration, resolution or model.
409concurrency_limitToo many generations already running for the plan.
422moderation_rejectedA content check rejected the prompt, an asset or the output. Refunded.
429rate_limitedRate limit exceeded. Retry-After is set.
503provider_unavailableNo healthy provider took the job. Refunded.

Limits and price

  • Concurrency follows your plan: 2 on Starter, 5 on Pro.
  • Pay-as-you-go is $0.012 per credit, with volume tiers. Packs never expire — see pricing.
  • 6 models are exposed. Never hardcode one: read /api/v1/models, because this family ships fast and ids change.