> ## Documentation Index
> Fetch the complete documentation index at: https://gccai.heqingsong.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Rückruf bei Aufgabenabschluss (Webhook)

> Gib beim Einreichen einer asynchronen Generierungsaufgabe eine Rückruf-URL an. Sobald die Aufgabe abgeschlossen ist (Erfolg oder Fehler), senden wir dir das Ergebnis per POST – kein Polling nötig.

Beim Einreichen asynchroner Generierungsaufgaben wie Video / Bild / Audio kannst du eine Rückruf-URL angeben. **Sobald die Aufgabe abgeschlossen ist (erfolgreich oder fehlgeschlagen)**, senden wir das Ergebnis aktiv per POST an deine URL, sodass du nicht ständig abfragen musst.

## Schnellstart

Füge beim Einreichen einer Aufgabe ein `webhook`-Feld zum Anfragetext hinzu:

```bash theme={null}
curl -X POST https://deine-zugangsdomain/v1/images/generations \
  -H "Authorization: Bearer DEIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a red apple on a table",
    "size": "1024x1024",
    "webhook": "https://your-server.com"
  }'
```

Nach Abschluss der Aufgabe senden wir eine POST-Anfrage an **`deine URL + /callback`**.

<Note>
  Andere asynchrone Aufgaben-Endpunkte (Video, Audio usw.) funktionieren genauso – füge einfach das `webhook`-Feld zum Anfragetext hinzu.
</Note>

## URL-Regeln

Die von dir angegebene `webhook` ist die **Basis-URL**, an die wir automatisch `/callback` anhängen:

| Deine `webhook`                | Wohin wir tatsächlich POST senden      |
| ------------------------------ | -------------------------------------- |
| `https://your-server.com`      | `https://your-server.com/callback`     |
| `https://your-server.com/api`  | `https://your-server.com/api/callback` |
| `https://your-server.com/api/` | `https://your-server.com/api/callback` |

Dein Server benötigt also einen Endpunkt, der `POST .../callback` akzeptiert.

## Was du erhältst

Der gesendete Inhalt ist **exakt derselbe wie die Antwort des Endpunkts „[Aufgabenstatus abrufen](/de/api-reference/tasks/status)"** – du kannst ihn mit derselben Parsing-Logik verarbeiten.

<CodeGroup>
  ```json Erfolg (status: completed) theme={null}
  {
    "id": "task_01KV7FXR8BEYS1BWHJCT3JMCJ5",
    "status": "completed",
    "progress": 100,
    "created": 1781589029,
    "completed": 1781589058,
    "actual_time": 29,
    "cost": 0.006,
    "credits_cost": 0.06,
    "result": {
      "images": [{ "url": ["https://.../result.png"], "expires_at": 1781675458 }]
    }
  }
  ```

  ```json Fehler (status: failed) theme={null}
  {
    "id": "task_xxx",
    "status": "failed",
    "progress": 100,
    "created": 1781589029,
    "completed": 1781589050,
    "error": { "message": "Grund des Fehlers...", "code": "" }
  }
  ```
</CodeGroup>

<Note>
  Bei Videoaufgaben liegt das Ergebnis in `result.videos`, bei Audio in `result.audios`.
</Note>

<Warning>
  Wir senden nur, wenn eine Aufgabe einen **Endzustand** erreicht (`completed` / `failed`); während der Verarbeitung senden wir nicht.
</Warning>

## Wiederholungen und Deduplizierung (wichtig)

* **Wiederholungen**: Wenn dein Server nicht innerhalb von etwa 10 Sekunden `2xx` zurückgibt oder `5xx` zurückgibt, wiederholen wir automatisch, bis zu **3 Mal**, in Abständen von etwa **10 s, 30 s und 60 s**. Schlagen alle 3 fehl, geben wir auf (innerhalb von etwa 2 Minuten).
* **Keine Wiederholung**: Gibt dein Endpunkt `4xx` zurück (als fehlerhafte URL / Anfrage gewertet), geben wir sofort ohne Wiederholung auf.
* **Deduplizierung**: Normalerweise wird eine Aufgabe nur einmal gesendet. In Extremfällen (z. B. ein Neustart auf unserer Seite nach dem Senden, aber vor der Bestätigung) **kannst du doppelte Sendungen erhalten**. Stelle unbedingt sicher, dass du **idempotent nach `id` (task\_id) dedupliziert**, um doppelte Verarbeitung zu vermeiden.

**Empfehlungen für deinen Empfangs-Endpunkt:**

<Steps>
  <Step title="So schnell wie möglich 2xx zurückgeben">
    Zuerst annehmen und in die Warteschlange stellen, dann asynchron verarbeiten – lass uns nicht auf den Abschluss deiner Verarbeitung warten.
  </Step>

  <Step title="Nach id deduplizieren">
    Verwende `id` (task\_id) als Idempotenzschlüssel, um doppelte Verarbeitung zu vermeiden.
  </Step>

  <Step title="Signatur konfigurieren und prüfen">
    Überprüfe in der Produktion die Herkunft der Rückrufanfragen und weise gefälschte ab.
  </Step>
</Steps>

## Anforderungen an die Rückruf-URL

Aus Sicherheitsgründen muss die Rückruf-URL Folgendes erfüllen:

| Anforderung           | Beschreibung                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------ |
| Öffentlich erreichbar | **Darf keine** interne / lokale Adresse sein (z. B. `127.0.0.1`, `10.x`, `192.168.x` werden abgelehnt) |
| Protokoll             | `http` oder `https` (`https` empfohlen)                                                                |
| Port                  | Standardports verwenden (`80` / `443`); nicht standardmäßige Ports können blockiert werden             |
| Domain                | Darf nicht auf unsere eigene Dienst-Domain zeigen                                                      |

URLs, die diese Anforderungen nicht erfüllen, werden verworfen (kein Senden, keine Wiederholung).

## Häufige Fragen

<AccordionGroup>
  <Accordion title="Ich habe eine Aufgabe mit Webhook eingereicht, aber keine Sendung erhalten?">
    Prüfe Punkt für Punkt:

    1. Ist die Aufgabe **tatsächlich abgeschlossen**? Prüfe die Aufgabendetails – ist `status` `completed` / `failed` (während der Verarbeitung wird nicht gesendet)?
    2. Ist deine URL **öffentlich erreichbar**? Können wir deinen `/callback` erreichen?
    3. Ist der Port ein Standardport (80 / 443)? Nicht standardmäßige Ports können durch Sicherheitsrichtlinien blockiert werden.
    4. Hat dein `/callback` **rechtzeitig 2xx zurückgegeben**? Bei 4xx geben wir sofort auf.
    5. Verwendest du `https`? Ist das Zertifikat gültig?
  </Accordion>

  <Accordion title="Warum ist url im Ergebnis ein Array?">
    Einige Modelle erzeugen mehrere Bilder auf einmal, daher kann `images[].url` ein Array sein – behandle es einfach als Array.
  </Accordion>

  <Accordion title="Laufen die Ergebnis-Links ab?">
    Enthält `result` ein `expires_at` (Unix-Zeitstempel), gibt dies die Ablaufzeit des Links an – sichere/speichere ihn rechtzeitig.
  </Accordion>

  <Accordion title="Wird der Status 'in Verarbeitung' gesendet?">
    Nein. Wir senden nur einmal, wenn die Aufgabe endgültig erfolgreich ist oder fehlschlägt.
  </Accordion>
</AccordionGroup>

## Minimales Empfänger-Beispiel

```python Python theme={null}
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        n = int(self.headers.get("Content-Length") or 0)
        body = self.rfile.read(n)
        data = json.loads(body)
        print("Aufgaben-Rückruf erhalten:", data["id"], data["status"])
        # TODO: nach id deduplizieren, Signatur prüfen, dann verarbeiten
        self.send_response(200); self.end_headers()
        self.wfile.write(b'{"ok":true}')

HTTPServer(("0.0.0.0", 443), H).serve_forever()
```

Gib so schnell wie möglich `200` zurück und führe deine Verarbeitungslogik asynchron im Hintergrund aus.
