Zum Inhalt springen

Best Practices für Webhooks

Prüfe die Signatur, reihe das Event ein (Datenbankzeile, Queue, Hintergrundjob) und gib sofort 2xx zurück. SpacePost wartet höchstens 15 Sekunden, und ein langsamer Handler führt zu Wiederholungen und Duplikaten.

Die Zustellung erfolgt mindestens einmal. Speichere die webhook-id jeder verarbeiteten Zustellung (ein Unique-Constraint genügt) und überspringe Wiederholungen.

const inserted = await db.insert(processedWebhooks).values({ id: webhookId }).onConflictDoNothing().returning();
if (inserted.length === 0) return new Response("duplicate", { status: 200 });

Verwende den rohen Body, lehne Zeitstempel ab, die älter als 5 Minuten sind, und vergleiche Signaturen in konstanter Zeit (das SDK und die Bibliotheken tun das). Siehe Signaturen prüfen.

Events können in falscher Reihenfolge eintreffen, besonders nach Wiederholungen. Vergleiche das created_at der Payload mit dem, was du gespeichert hast, und wende nur Änderungen an, die den Zustand vorwärtsbringen. Das last_event von SpacePost folgt derselben Regel.

Event Typische Aktion
email.bounced Markiere die Adresse in deiner Datenbank als ungültig; sende nicht mehr an sie.
email.complained Melde den Nutzer sofort von nicht notwendigen E-Mails ab.
email.delivery_delayed Meist nichts; alarmiere, wenn es sich um eine zeitkritische E-Mail handelt (Passwort-Zurücksetzung).
email.failed Logge data.failed.reason, alarmiere und wiederhole gegebenenfalls mit einer Korrektur.
email.suppressed Ein Empfänger stand auf deiner Sperrliste; zeige das in deiner Admin-Oberfläche an.

Abonniere nur die Events, die du verarbeitest. Weniger Events bedeuten weniger Traffic und weniger Fehler.

  • Liefere über HTTPS mit einem gültigen Zertifikat aus.
  • Logge keine Secrets und keine vollständigen Payloads mit personenbezogenen Daten.
  • Verwende einen eigenen Pfad ohne anderes Verhalten und gib einen generischen Body zurück.
  • Bewahre das signing_secret in einem Secret Manager auf, nicht in der Versionsverwaltung.

Beobachte das Zustellungs-Log im Dashboard oder alarmiere bei wiederholten Fehlern: Ist dein Endpoint länger als etwa 27 Stunden nicht erreichbar, sind alle Wiederholungen aufgebraucht, und du musst manuell erneut senden.