Seedance 2.0 FastAPI-Referenz
Alles, was du brauchst, um Seedance 2.0 Fast aus Code aufzurufen: ein Schnellstart in drei Schritten, jedes Feld mit seinen Limits, die Preisformel, Webhooks und Idempotenz. Die MCP-Tools laufen über dieselbe /v1-API; mit einer MCP-Anmeldung verbrauchst du das Kreativguthaben, mit einem API-Schlüssel das Entwickler-API-Guthaben.
Zugang zur Entwickler-API gibt es auf Antrag.
Schnellstartin drei Aufrufen
Setze einen Schlüssel, sende den Auftrag mit einer Preisobergrenze und lies dann das Ergebnis.
- 01
Schlüssel setzen
Zugang zur Entwickler-API gibt es auf Antrag: Beantrage ihn im Studio unter API-Schlüssel. Der Schlüssel wird einmal angezeigt, also speichere ihn in einer Umgebungsvariable.
export API_KEY="sk_test_…" - 02
Auftrag senden
Sende den Clip per POST mit einem Idempotency-Key und der Obergrenze max_credits (oder einer quote_id). Du bekommst sofort 202 und einen Auftrag in der Warteschlange, und die Credits werden reserviert.
curl https://api.pershot.app/v1/videos/generations \ -H "Authorization: Bearer $API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "model": "seedance-2.0-fast", "prompt": "Perfume mist in hard side light. Slow push-in, black background, grain.", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9", "generate_audio": true, "max_credits": 34 }'{ "id": "job_01J9ZK4T8W", "object": "job", "kind": "video", "status": "queued", "money_status": "reserved", "queue_position": 2, "requested_model": "seedance-2.0-fast", "credits_quoted": 34, "credits_charged": null } - 03
Ergebnis lesen
Rufe den Auftrag per GET ab, bis sein Status succeeded ist. outputs[].url ist signiert und läuft nach 24 Stunden ab, also lade herunter, was du behalten willst.
curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \ -H "Authorization: Bearer $API_KEY"
Parameterund Limits
Gelesen aus dem OpenAPI-Dokument, das aus denselben Schemas erzeugt wird, gegen die die API validiert. Unbekannte Felder werden abgelehnt.
| Feld | Typ | Erlaubt | Hinweise |
|---|---|---|---|
modelErforderlich | string | seedance-2.0-fast · seedance-2.0-mini · auto | Die Modell-ID. |
promptErforderlich | string | 2–2.000 Zeichen | Was generiert werden soll: das Motiv, die Kamera und das Licht. |
durationStandard 5 | integer | 4–15 | Länge der Ausgabe in ganzen Sekunden, bis 15. |
resolutionStandard "720p" | string | 480p · 720p | Ausgabeauflösung. 480p für Entwürfe, 720p für die Auslieferung; jede ist eine eigene Generierung. |
aspect_ratioStandard "16:9" | string | 16:9 · 9:16 · 1:1 | Bildformat. |
generate_audioStandard true | boolean | – | Natives Audio. Der Preis ist mit und ohne gleich. |
image_urlOptional | string | https-URL | Startbild für Video; das Ausgangsbild für die Bearbeitungsmodelle. Eine öffentliche https-URL oder eine Upload-URL. |
reference_image_urlsOptional | string[] | Bis zu 9 · https-URL | Referenzbilder für Motiv und Stil. Verweise im Prompt mit @image1, @image2 auf sie. |
seedOptional | integer | 0–2.147.483.647 | Wird akzeptiert und ignoriert: Seedance 2.0 nimmt keinen Seed an. |
quote_idOptional | string | qt_… | Ausführung zu einem Preisangebot von POST /v1/quotes, 10 Minuten gültig. |
max_creditsOptional | number | > 0 | Das Höchste, was dieser Auftrag kosten darf. Darüber wird der Auftrag abgelehnt, nie berechnet. |
webhook_urlOptional | string | https-URL | Eine https-URL, die die Ereignisse des Auftrags empfängt. |
end_user_idOptional | string | 1–128 Zeichen | Für freigegebene Entwicklerkonten (Zugang auf Antrag): deine eigene Nutzer-ID für diese Anfrage, sichtbar in der Nutzung. |
project_idOptional | string | prj_… | |
shot_idOptional | string | sht_… | |
routing_preferenceOptional | string | stability · speed | |
enhanceOptional | object | – |
Sende genau eins von beiden: quote_id oder max_credits. Dieser Endpunkt lehnt model "auto" ab: Für Videos ruf zuerst POST /v1/auto/plan auf und sende dann das gewählte Modell mit max_credits.
- Ratenlimit und Parallelität
- Standardmäßig 60 Anfragen pro Minute pro Schlüssel und 3 gleichzeitige Aufträge pro Konto. Mehr Schlüssel bringen keine zusätzliche Parallelität.
Limits
Aus derselben Tabelle gelesen, gegen die die API prüft. Jede Zeile zeigt, wer das Limit prüft und was passiert, wenn es überschritten wird.
- ErzwungenWir prüfen es und antworten mit 400, bevor ein Preisangebot erstellt oder etwas reserviert wird.
- Beim LieferantenDer Anbieter prüft es. Ein Auftrag, den er ablehnt, schlägt fehl, und es wird nichts berechnet.
- EmpfohlenNiemand prüft es. Wenn du darunter bleibst, bekommst du bessere Ergebnisse.
| Limit | Wert | Einheit | Wer prüft | Bei Überschreitung |
|---|---|---|---|---|
| Anfrage | ||||
Prompt-Längeprompt | 2 bis 2.000 | Zeichen | Erzwungen | 400 invalid_request bei prompt, vor jedem Preisangebot und jeder Reservierung. |
Prompt auf Englischprompt | bis 1.000 | Wörter | Empfohlen | Wird akzeptiert. Einem längeren Prompt folgt das Modell womöglich weniger genau. |
Prompt auf Chinesischprompt | bis 500 | chinesische Zeichen | Empfohlen | Wird akzeptiert. Einem längeren Prompt folgt das Modell womöglich weniger genau. |
Dauerduration | 4 bis 15Standard 5 | Sekunden | Erzwungen | 400 invalid_request bei duration. Nur ganze Sekunden. |
Auflösungresolution | 480p, 720pStandard 720p | – | Erzwungen | 400 invalid_request bei resolution. |
Seitenverhältnisaspect_ratio | 16:9, 9:16, 1:1Standard 16:9 | – | Erzwungen | 400 invalid_request bei aspect_ratio. |
Seedseed | Ignoriert | – | Beim Lieferanten | Wird akzeptiert, aber nicht gesendet: Seedance 2.0 nimmt keinen Seed an, ein Seed wiederholt also kein Ergebnis. |
Länge des Eingabevideosinput_video_seconds | 2 bis 15 | Sekunden | Erzwungen | 400 invalid_request bei POST /v1/quotes. Generierungen über die API nehmen kein Eingabevideo an. |
| Bilder, die du sendest | ||||
Referenzbilderreference_image_urls | bis 9 | Bilder | Erzwungen | 400 invalid_request bei reference_image_urls. |
Startbild oder Referenzenreference_image_urls | image_url oder reference_image_urls, nicht beides | – | Erzwungen | 400 invalid_request bei reference_image_urls. Seedance 2.0 nutzt pro Auftrag einen der beiden Modi. |
Seitenlänge des Bildesimage_urlreference_image_urls | 300 bis 6.000 | px pro Seite | Erzwungen bei Uploads | Uploads: 400 invalid_request bei image_url oder reference_image_urls.N, vor jedem Preisangebot und jeder Reservierung. Andere Links: Der Anbieter lehnt den Auftrag ab, und es wird nichts berechnet. |
Bildformimage_urlreference_image_urls | 0,4 bis 2,5 | Breite ÷ Höhe | Erzwungen bei Uploads | Uploads: 400 invalid_request bei image_url oder reference_image_urls.N, vor jedem Preisangebot und jeder Reservierung. Andere Links: Der Anbieter lehnt den Auftrag ab, und es wird nichts berechnet. |
Upload-Größefile | bis 10 | MB | Erzwungen | POST /v1/uploads antwortet mit 400 invalid_request bei file. |
Upload-Formatefile | JPEG, PNG, WebP | – | Erzwungen | Wird aus der Datei selbst gelesen, nicht aus ihrem Namen. Alles andere: 400 invalid_request bei file. |
Größe verlinkter Bilderimage_urlreference_image_urls | bis 30 | MB | Beim Lieferanten | Für Bilder, die von anderen Hosts verlinkt sind. Der Anbieter lehnt den Auftrag ab, und es wird nichts berechnet. |
Formate verlinkter Bilderimage_urlreference_image_urls | JPEG, PNG, WebP, BMP, TIFF, GIF, HEIC, HEIF | – | Beim Lieferanten | Für Bilder, die von anderen Hosts verlinkt sind. Der Anbieter lehnt den Auftrag ab, und es wird nichts berechnet. |
| Ausgabe | ||||
| Ausgabepixel | 480p16:9864×4969:16496×8641:1640×640720p16:91280×7209:16720×12801:1960×960 | px | Beim Lieferanten | Vom Modell für jede Auflösung und jedes Seitenverhältnis festgelegt. |
| Bildrate | 24 | fps | Beim Lieferanten | Für jedes Video gleich. |
| Ausgabeformat | MP4 | – | Beim Lieferanten | Jedes Video ist ein MP4, mit Ton, wenn generate_audio aktiv ist. |
| Links | ||||
| Upload-Link | 7 | Tage | Erzwungen | Danach antwortet der Link mit 403. Lade die Datei erneut hoch. |
| Ausgabe-Link | 24 | Stunden | Erzwungen | Danach antwortet der Link mit 403. Ruf den Auftrag erneut per GET ab, um einen neuen Link zu bekommen. Die Datei selbst wird 12 Monate aufbewahrt (outputs_expire_at des Auftrags nennt das Datum), länger, wenn das Ergebnis in der Mediathek gespeichert oder in einem Projekt verwendet wird. |
Wir laden nie Bilder von anderen Hosts, daher prüft bei solchen Links der Anbieter die Größe, und ein Auftrag, den er ablehnt, wird nicht berechnet. Dieselben Limits gibt es auch als JSON: GET /v1/models liefert für jedes Modell ein limits-Objekt.
Preiseoffen nachgerechnet
Jeder Auftrag bekommt vor dem Start ein Preisangebot in Credits (1 US$ = 100 Credits). Der Satz pro Sekunde dient der Budgetplanung; POST /v1/quotes liefert den genauen Betrag.
Credits = ceil(BytePlus-Listenpreis × 0,55 × 100), wobei Listenpreis = (Eingabe-s + Ausgabe-s) × Breite × Höhe × 24 ÷ 1024 × Listensatz| Spezifikation | Pro Sekunde (API) | 5 s | 10 s | 15 s |
|---|---|---|---|---|
| 480pOhne Videoeingabe | 0,031 $Mit Eingabevideo: 0,019 $/s≈ 322 s pro 10 $ | 16 cr≈ 0,16 $ | 31 cr≈ 0,31 $ | 47 cr≈ 0,47 $ |
| 720pOhne Videoeingabe | 0,067 $Mit Eingabevideo: 0,040 $/s≈ 149 s pro 10 $ | 34 cr≈ 0,34 $ | 67 cr≈ 0,67 $ | 100 cr≈ 1,00 $ |
Abgelehnte oder fehlgeschlagene Aufträge werden nicht berechnet.
Webhooksund Idempotenz
Wiederholte Anfragen werden nie doppelt berechnet, und du musst nicht ständig abfragen.
- Idempotenz
- Jeder Generierungs-POST braucht einen Idempotency-Key (1 bis 255 sichtbare ASCII-Zeichen). Derselbe Schlüssel innerhalb von 24 Stunden liefert denselben Auftrag mit HTTP 200, also erzeugt oder berechnet eine Wiederholung nach einem Timeout nie einen zweiten Auftrag.
- Abgelehnte Prompts
- Ein Prompt, den die Vorprüfung ablehnt (422 content_rejected), erzeugt nichts, also kannst du denselben Schlüssel mit einem neuen Prompt wieder verwenden.
- Ereignisse
job.queuedjob.processingjob.succeededjob.failedjob.cancelled- Signatur
- X-Signature enthält t, die Unix-Zeit, und v1, einen HMAC-SHA256 über t, einen Punkt und den Rohbody, mit deinem whsec_-Secret als Schlüssel. Lehne Zeitstempel ab, die älter als fünf Minuten sind, und entferne Duplikate anhand von X-Event-Id.
- Zustellung
- Ein 2xx innerhalb von 10 Sekunden gilt als zugestellt. Fehlgeschlagene Zustellungen werden nach 1 min, 5 min, 30 min, 2 h und 6 h wiederholt. Weiterleitungen werden nicht verfolgt.
{
"id": "evt_01J9ZKB1QX",
"type": "job.succeeded",
"created_at": "2026-09-29T14:02:31Z",
"data": {
"job": {
"id": "job_01J9ZK4T8W",
"object": "job",
"kind": "video",
"status": "succeeded",
"money_status": "settled",
"requested_model": "seedance-2.0-fast",
"credits_charged": 34,
"outputs": [
{
"kind": "video",
"url": "https://…/job_01J9ZK4T8W.mp4?sig=…"
}
]
}
}
}import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(header, rawBody, secret, toleranceSec = 300) {
let t = null;
const signatures = [];
for (const item of (header ?? "").split(",")) {
const [key, value] = item.split("=", 2);
if (key === "t") t = Number(value);
if (key === "v1") signatures.push(Buffer.from(value, "hex"));
}
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}
// verifyWebhook(req.headers["x-signature"], rawBody, process.env.WEBHOOK_SECRET)
// Answer 2xx quickly, and skip an X-Event-Id you have already handled.Fehlerund was zu tun ist
Jeder Fehler hat dieselbe Form: ein error-Objekt mit code, message, param und request_id. Die, auf die du am ehesten triffst:
| Code | HTTP | Was tun |
|---|---|---|
invalid_request | 400 | Korrigiere das Feld, das in param genannt wird. |
unauthorized | 401 | Prüfe den Schlüssel und den Bearer-Header. |
insufficient_credits | 402 | Lade auf und versuch es dann mit demselben Idempotency-Key erneut. |
forbidden_model | 403 | Füge das Modell oder Tool im Studio zu den erlaubten Modellen und Tools des Schlüssels hinzu, oder nutze einen anderen Schlüssel. Tools wie „Verbessern“ brauchen einen eigenen Eintrag. |
quote_expired | 409 | Hol ein neues Preisangebot ein; Preisangebote gelten 10 Minuten. |
price_changed | 409 | Der Preis ist über deine Obergrenze gestiegen. Hol ein neues Preisangebot ein oder erhöhe max_credits. |
content_rejected | 422 | Es wurde nichts berechnet. Ändere den Prompt oder die Bilder. |
rate_limited | 429 | Warte die Zeit aus Retry-After ab und versuch es dann erneut. |
upstream_unavailable | 503 | Das Modell ist nicht verfügbar. Versuch es später erneut; ein Auftrag, der nie startet, wird nicht berechnet. |