Skip to main content
Jeder Generierungs-Endpoint ist asynchron. Statt den GET-Endpoint abzufragen, kannst du eine webhook_url übergeben, und Samsa sendet per POST ein signiertes Event dorthin, sobald der Job einen terminalen Status erreicht.

Einen Webhook anfordern

Füge webhook_url zu einer beliebigen Generierungsanfrage hinzu. Sie gilt pro Anfrage — verschiedene Jobs können auf verschiedene URLs zielen.
Webhooks sind eine Bequemlichkeit, nicht die Source of Truth. Wenn jeder Zustellversuch fehlschlägt, ist das Job-Ergebnis weiterhin über seinen GET-Endpoint verfügbar. Frage als Fallback für alles Kritische ab.

Events

Webhooks feuern nur bei terminalen Übergängen — completed oder failed. Jobs, die cancelled sind, emittieren keinen Webhook.

Payload

Der Request-Body ist JSON. Das data-Objekt hat dieselbe Form, die du vom GET-Status-Endpoint des Jobs erhältst.
Bei einem failed-Event ist status gleich "failed" und data trägt ein error-Objekt mit derselben inneren Form wie das Error-Envelope.

Signatur-Header

Jede Zustellung trägt drei Header:
Das Schema ist Svix-kompatibel: HMAC-SHA256 über {webhook-id}.{webhook-timestamp}.{raw-body}, base64-kodiert, mit v1, präfixiert.
Signiere und verifiziere über die rohen Request-Bytes genau so, wie sie empfangen wurden — nie über eine neu serialisierte Kopie. Neu-Serialisieren (Keys umordnen, Whitespace ändern) verändert die Bytes und bricht die Signatur.

Die Signatur verifizieren

Dein webhook_secret pro Key liegt in der App unter Settings → API Keys (jeder Key hat sein eigenes Secret; rotiere es unabhängig vom Key). Die Snippets unten sind gegen einen festen Test-Vektor verifiziert — führe sie unverändert aus, und sie geben true zurück, sodass du bestätigen kannst, dass deine Implementierung die Signatur Byte für Byte reproduziert, bevor du ein echtes Secret einbindest.
Der Body des Test-Vektors ist ein fester Referenz-String, sodass seine exakten Bytes sich nie ändern und die Signatur reproduzierbar bleibt — er ist absichtlich nicht das Live-Event-Payload, das oben gezeigt wird. Die Signaturverifizierung läuft immer über die exakten rohen Bytes, die du empfängst, welche Form sie auch haben, das ist also rein ein Selbsttest für deinen Verifier. Ebenso ist webhook-id ein opaker, pro Event stabiler String — behandle ihn wie ein Token, parse ihn nie.
Erzwinge in Produktion immer auch das Zeitstempel-Fenster: lehne die Zustellung ab, wenn |now − webhook-timestamp| > 300 Sekunden.

Retries und Zustellregeln

  • Erfolg ist jede 2xx-Antwort, die innerhalb eines 10-Sekunden-Timeouts zurückkommt (Connect-Timeout 5s). Ein 3xx wird als Fehlschlag behandelt — Samsa folgt keinen Redirects.
  • Bei einem Fehlschlag wiederholt Samsa mit dem ersten Versuch plus 5 Retries6 Zustellversuche insgesamt — mit Back-off 5s → 30s → 2m → 15m → 1h.
  • Nach dem letzten Versuch wird die Zustellung verworfen (und geloggt). Das Job-Ergebnis bleibt über seinen GET-Endpoint abfragbar.
  • Endpoints müssen HTTPS sein. Antworte schnell (2xx) und erledige schwere Verarbeitung asynchron, damit du das 10-Sekunden-Fenster nie überschreitest.
Nutze die stabile webhook-id, um deinen Handler idempotent zu machen. Eine wiederholte Zustellung verwendet dieselbe webhook-id, sodass du ein bereits verarbeitetes Event sicher ignorieren kannst.