Tasks
Einen Task erstellen, seinen Zustand verfolgen, das Ergebnis lesen – und wait, Task-Liste, retry und purge nutzen.
Jede Generierung ist ein Task. Du erstellst ihn mit einem Aufruf, er läuft von allein, und du holst das Ergebnis ab, sobald es fertig ist – per Abfrage, durch Warten beim ersten Aufruf oder per Webhook.
POST /jobs/createTasktaskIdGET /jobs/recordInfostateGET output.assets[].url
Einen Task erstellen
curl -X POST "https://api.popnow.ai/api/v1/jobs/createTask" \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "alibaba/wan-3.0/image-to-video",
"input": {
"image_url": "https://media.popnow.ai/movie/lighthouse.webp",
"prompt": "Waves roll in slowly, the camera drifts toward the lighthouse",
"resolution": "480p",
"duration_seconds": 5
},
"callBackUrl": "https://your-app.example.com/hooks/popnow"
}'Body
| Feld | Pflicht | Bedeutung |
|---|---|---|
model | Ja | Die Modell-ID aus Modelle |
input | Ja | Die Felder des Modells, geprüft gegen sein Eingabeschema |
callBackUrl | Nein | Öffentliche HTTPS-URL, die den fertigen Task erhält. Siehe Webhooks |
quoteId, expectedCredits | Nein | Einen mit jobs/quote bestätigten Preis festschreiben |
Header
| Header | Bedeutung |
|---|---|
Authorization: Bearer sk-popnow-… | Dein API-Schlüssel |
Idempotency-Key | Dringend empfohlen. Eine Wiederholung mit demselben Schlüssel liefert den ursprünglichen Task. Siehe Idempotenz |
X-PopNow-Retention | Optional. Wie viele Sekunden Ausgaben und Prompt dieses Tasks aufbewahrt werden. Kann die Aufbewahrung nur verkürzen, nie verlängern |
Accept-Language | Optional. Sprache der Fehlermeldungen. Siehe Fehler |
Antwort
Ein neuer Task kommt als HTTP 202 zurück:
{
"code": 200,
"msg": "success",
"data": {
"taskId": "job_01JH8Z4Q5W2N7R3K9M6P1C0VXD",
"state": "queued",
"estimatedCredits": 34,
"estimatedCost": "0.34",
"deadlineAt": "2026-10-16T09:40:00Z"
},
"request_id": "req_…"
}202 heißt angenommen, nicht fertig. estimatedCredits ist der von deinem Guthaben reservierte Betrag – das Maximum, das dieser Task kosten kann (estimatedCost ist derselbe Betrag in US-Dollar). Schlägt das Erstellen fehl, wird nichts angelegt und nichts reserviert; code sagt dir, warum (Fehler).
Zustände
queuedrunningsucceededfailedexpired| Zustand | Endgültig? | Bedeutung |
|---|---|---|
queued | Nein | Angenommen, wartet auf den Start |
running | Nein | Wird generiert |
succeeded | Ja | Fertig; die Dateien stehen in output.assets |
failed | Ja | Konnte nicht fertig werden; siehe errorCode und errorMessage. Die Reservierung wird freigegeben |
expired | Ja | Hat die Frist überschritten. Die Reservierung wird freigegeben |
canceled | Ja | Nur in alten Einträgen. Ein angenommener Task lässt sich heute nicht abbrechen |
Behandle jeden unbekannten Zustand als „noch nicht fertig“ und frag weiter ab.
Polling sparen mit wait
Häng ?wait=<Sekunden> (bis 60) an createTask, dann bleibt die Verbindung offen, bis der Task fertig ist oder die Zeit abläuft:
- Rechtzeitig fertig → HTTP
200mit dem vollständigen Task-Eintrag, im selben Format wierecordInfo. Prüfdata.state: endgültig heißt nicht immer erfolgreich. - Nicht fertig → das gewohnte
202, und du pollst weiter oder wartest auf den Webhook.
Gut für Bilder und kurzes Audio; Videos dauern fast immer länger als 60 Sekunden. Ein früher Verbindungsabbruch stoppt den Task nicht.
Einen Task lesen
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_01JH8Z4Q5W2N7R3K9M6P1C0VXD" \
-H "Authorization: Bearer $POPNOW_API_KEY"| Feld | Bedeutung |
|---|---|
taskId, model, state | Welcher Task, welches Modell, wie weit er ist |
input | Die tatsächlich verwendete Eingabe, inklusive des gewählten seed, falls du keinen geschickt hast |
output.assets[] | Die Dateien. Jede hat url, expiresAt, mime und je nach Fall width, height, durationSeconds, bytes, role |
errorCode, errorMessage | Warum ein Task gescheitert ist. Verzweige nach errorCode, zeig errorMessage an |
credits, cost, settled | Solange settled false ist, ist credits die Reservierung; bei true die endgültige Abbuchung. cost ist derselbe Betrag in US-Dollar |
createdAt, completedAt, deadlineAt | Zeitstempel; deadlineAt ist der Zeitpunkt, an dem ein unfertiger Task abläuft |
retention.outputsExpireAt | Wann die Dateien dieses Tasks gelöscht werden |
contentState | present – oder expired / purged, sobald der Inhalt entfernt wurde |
Drei verschiedene Ablaufzeiten
deadlineAt– wie lange der Task laufen darf. Danach wird erexpired, und die Reservierung wird freigegeben.output.assets[].expiresAt– wie lange dieser eine signierte Link gilt, etwa 20 Minuten. Lies den Task erneut für einen frischen Link; die Datei selbst ist noch da.retention.outputsExpireAt– wann die gespeicherte Datei entfernt wird. Lade alles, was du behalten willst, vorher herunter oder speichere es in deiner Asset-Bibliothek.
Was in output steckt
Die meisten Tasks liefern ein Asset. Manche liefern mehr: mehrere Bilder, wenn das Modell Varianten erzeugt; bei der Videoverlängerung zuerst den zusammengesetzten Clip (role: "video") und dann das neue Segment (role: "segment"); bei der Ebenentrennung ein Basisbild plus transparente Ebenen (jeweils mit einem layer-Objekt). Speech-to-Text liefert das Transkript in output.text.
Asset-Links sind Inhaberlinks: Wer die URL hat, kann die Datei herunterladen, bis sie abläuft. Schick beim Abrufen keinen API-Schlüssel mit.
Webhooks zuerst, Polling als Rückfallebene
Polling funktioniert, aber ein Webhook ist für beide Seiten günstiger: Du erfährst vom Ergebnis, sobald es existiert, und verbrauchst dazwischen keine Anfragen. Eine robuste Integration nutzt beides – Webhooks im Normalfall und gelegentlich einen recordInfo-Durchlauf für Tasks, deren Webhook nicht ankam.
Wenn du pollst, lass Luft: alle 2–3 Sekunden bei Bildern, alle 10–15 Sekunden bei Videos, und hör bei deadlineAt auf.
Die Task-Liste
GET /api/v1/jobs liefert die Tasks dieses Schlüssels, neueste zuerst, ohne Eingaben und Ausgaben:
curl "https://api.popnow.ai/api/v1/jobs?state=failed&from=2026-10-01&limit=50" \
-H "Authorization: Bearer $POPNOW_API_KEY"Filter: from und to (UTC-Daten, höchstens 92 Tage auseinander; Standard sind die letzten sieben Tage), state, model, limit (bis 100). Ist hasMore true, gib nextCursor als cursor mit denselben Filtern zurück.
Einen fehlgeschlagenen Task wiederholen
POST /api/v1/jobs/retry mit { "taskId": "…" } erzeugt aus einem failed- oder expired-Task einen neuen Task mit der ursprünglichen Eingabe zum heutigen Preis. Der Original-Task bleibt unverändert. Solange der Quell-Task nicht fertig ist, kommt 409; einen erfolgreichen Task kann man nicht wiederholen – leg stattdessen einen neuen an.
Den Inhalt eines Tasks löschen
POST /api/v1/jobs/purge mit { "taskId": "…" } löscht die Dateien, das Ergebnis und den gespeicherten Prompt des Tasks. Der Abrechnungseintrag bleibt: Betrag, Modell, Zustand und Zeitstempel bleiben erhalten, und die Antwort sagt das mit billingRetained: true. Nur fertige Tasks lassen sich löschen, und ein wiederholter Aufruf ist unbedenklich.

