Alle Artikel
Integrationen & Analytics

Webhook-Signaturen

Zustellungen von Signalist werden mit einem Secret signiert, das nur du und Signalist kennen. Dein Empfänger kann an der Signatur prüfen, dass eine Anfrage von Signalist stammt und unterwegs nicht verändert wurde. Neue Webhooks sind von Anfang an signiert. Ein Webhook, der vor dem 14. Oktober 2026 angelegt wurde, liefert weiter unsigniert aus, wie bisher, bis du die Signatur für ihn einschaltest (siehe „Dein Signing Secret“). Dieser Artikel erklärt, wie du an dein Secret kommst, wie du eine Zustellung prüfst und wie du das Secret rotierst. Wie du einen Webhook anlegst und welche Payload Formate es gibt, steht in API Schlüssel und Webhooks sicher verwenden.

Was eine signierte Zustellung mitbringt

Jede signierte Anfrage trägt diese Header:

  • X-Signalist-Signature: t=<Unix-Sekunden>,v1=<Hex>: die Signatur.
  • X-Signalist-Webhook-Id: der Webhook, der sie gesendet hat.
  • X-Signalist-Delivery-Id: eine ID pro Lead und Ereignis. Eine Wiederholung trägt dieselbe ID und ein neues t.
  • Content-Type: application/json

Ein älterer Webhook, der noch nicht umgestellt wurde, sendet keinen der X-Signalist--Header.

Dein Signing Secret

Das Secret beginnt mit whsec_. Signalist zeigt es einmal an, im Dialog Webhook created: copy your signing secret direkt nach dem Anlegen des Webhooks. Kopiere es in deinen Empfänger. Der Dialog lässt sich nur mit I have copied the secret schließen.

  • Du hast das Secret verloren. Öffne Integrations → Webhooks, öffne das Zeilenmenü (More actions) und wähle Rotate secret. Bestätige mit Rotate. Ein neues Secret wird einmal angezeigt.

  • Dein Webhook ist älter als die Signatur. Webhooks, die vor der Einführung der Signatur angelegt wurden, zeigen in der Spalte Signing den Eintrag Secret not yet viewed. Ihre Zustellungen sind noch nicht signiert: Sie werden genau wie bisher gesendet, ohne die Signatur-Header, und bleiben so, bis du die Signatur einschaltest. Das geht auf drei Wegen:

    • Wähle im Zeilenmenü Reveal secret once, um das Secret zu sehen. Es lässt sich nur einmal anzeigen. Ein zweiter Versuch wird abgelehnt mit „This secret was already shown once. Use "Rotate secret" to get a new one.“, und der Menüeintrag ist nach dem Aktualisieren der Seite weg;
    • wähle im Zeilenmenü Rotate secret;
    • ändere die URL des Webhooks mit Replace URL. Wähle danach Reveal secret once, um das Secret zu sehen.

    Von da an wird jede Zustellung an diesen Webhook signiert, geht nur an eine öffentliche Adresse und folgt keiner Weiterleitung, wie bei einem neuen Webhook. Eine Rückkehr zur unsignierten Zustellung gibt es nicht. Leitet deine aktuelle URL auf eine andere Adresse weiter, ersetze sie durch die Adresse, auf die sie weiterleitet, bevor du die Signatur einschaltest.

So prüfst du eine Zustellung

  1. Lies den rohen Body der Anfrage genau so, wie er ankommt, bevor du JSON parst.
  2. Teile den Signatur-Header an den Kommas. Nimm t und jedes v1.
  3. Berechne HMAC-SHA256 mit dem gesamten Secret (inklusive Präfix whsec_) als Schlüssel über den Text <t>.<roher Body>, als Hex in Kleinbuchstaben.
  4. Vergleiche das Ergebnis in konstanter Zeit mit jedem v1 (zum Beispiel crypto.timingSafeEqual in Node oder hmac.compare_digest in Python). Akzeptiere die Anfrage, wenn eines passt.
  5. Lehne die Anfrage ab, wenn t mehr als 5 Minuten von deiner Uhr abweicht. So verhinderst du Wiedereinspielung.
  6. Speichere X-Signalist-Delivery-Id und ignoriere eine Zustellung, die du schon verarbeitet hast. Eine Wiederholung trägt sie erneut.

Antworte mit einem 2xx-Status, um eine Zustellung zu bestätigen.

Ein Beispiel in Node. Es akzeptiert eine echte Zustellung und lehnt einen veränderten Body, ein falsches Secret und einen Zeitstempel ab, der älter als 5 Minuten ist:

import crypto from "node:crypto";

function verify(header, rawBody, secret, now = Date.now() / 1000) {
  const parts = header.split(",").map((p) => p.split("="));
  const t = parts.find(([k]) => k === "t")?.[1];
  const signatures = parts.filter(([k]) => k === "v1").map(([, v]) => v);
  if (!t || Math.abs(now - Number(t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return signatures.some(
    (s) => s.length === expected.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)),
  );
}

Das Secret rotieren

Wähle im Zeilenmenü Rotate secret. Das alte Secret funktioniert noch 24 Stunden. In dieser Zeit trägt jede Anfrage zwei v1-Werte, zuerst den neuen, dann den alten. So kannst du deinen Empfänger in Ruhe umstellen: Akzeptiere die Anfrage, wenn einer der beiden Werte passt. Die Spalte Signing zeigt „Rotating: old secret valid until“ und das Datum.

Rotierst du innerhalb dieser 24 Stunden erneut, wird das Secret der ersten Rotation sofort ungültig.

Rotierst du das Secret eines älteren Webhooks, stellt das ihn auch auf signierte Zustellung um: Danach wird jede Zustellung an ihn signiert, geht nur an eine öffentliche Adresse und folgt keiner Weiterleitung.

Ein Testereignis senden

Wähle im Zeilenmenü oder im Bearbeiten-Dialog Send test event. Signalist sendet ein signiertes Beispiel, markiert mit "event": "test", an deine URL. Es wird kein echter Lead gesendet, und in deine Listen wird nichts geschrieben. Der Dialog zeigt Delivered. oder Not delivered., was gesendet wurde und die Antwort deines Empfängers (die ersten 500 Zeichen). Ein Testereignis zählt nicht zum Zustellstatus des Webhooks in der Tabelle.

  • Du kannst pro Webhook alle 15 Sekunden ein Testereignis senden. Früher siehst du „A test event was just sent. Wait a few seconds and try again.“
  • Signalist wartet höchstens 10 Sekunden auf eine Antwort und liest höchstens 64 KB davon.
  • Weiterleitungen werden nicht verfolgt. Ein 301 oder 302 erscheint als Not delivered, und das Ziel der Weiterleitung wird nicht aufgerufen.
  • Eine URL auf einer privaten Netzwerkadresse kann keine Webhooks empfangen. Siehe „Eine Zustellung zeigt Not sent“ in API-Schlüssel und Webhooks sicher verwenden.
  • Ein Testereignis ist immer signiert und läuft immer durch diese Prüfungen, auch bei einem älteren Webhook. Es stellt den Webhook nicht auf signierte Zustellung um.

Fehlerbehebung

ProblemWas zu tun ist
Die Signatur passt nieBerechne sie über den rohen Body der Anfrage, Byte für Byte, nicht über neu serialisiertes JSON. Nimm das gesamte Secret inklusive whsec_ und den Text <t>.<roher Body>.
Die Signatur passte bis heuteDas Secret wurde vielleicht rotiert. In den 24 Stunden nach einer Rotation trägt eine Anfrage zwei v1-Werte. Akzeptiere sie, wenn einer passt, und stelle auf das neue Secret um.
Die Zustellungen eines älteren Webhooks tragen keine SignaturDer Webhook zeigt Secret not yet viewed und liefert noch wie bisher aus. Wähle im Zeilenmenü Reveal secret once oder Rotate secret, oder ersetze seine URL. Von da an sind seine Zustellungen signiert.
Ich habe das Secret verlorenWähle im Zeilenmenü Rotate secret.
Reveal secret once fehltDas Secret eines Webhooks, der mit Signatur angelegt wurde, wurde einmal beim Anlegen angezeigt. Wähle Rotate secret, um ein neues zu bekommen.
Send test event meldet Not deliveredLies die Antwort deines Empfängers im Dialog. Wenn dein Empfänger die Signatur prüft, achte darauf, dass er das aktuelle Secret und den rohen Body verwendet.

Häufig gestellte Fragen

Muss ich die Signatur prüfen?

Nein. Dein Empfänger funktioniert auch ohne Prüfung weiter. Die Zustellungen neuer Webhooks und älterer Webhooks, die du umgestellt hast, sind trotzdem signiert, du kannst die Prüfung also einbauen, wann du so weit bist.

Warum liefert ein älterer Webhook ohne Signatur aus?

Damit ein Empfänger, der vor der Einführung der Signatur gebaut wurde, unverändert weiterläuft. Signatur, Prüfung auf private Adressen und das Ende der Weiterleitungen werden für so einen Webhook erst eingeschaltet, wenn du sein Secret anzeigst oder rotierst oder seine URL änderst.

Kann ich nach dem Einschalten der Signatur zur unsignierten Zustellung zurück?

Nein. Ein Webhook, der einmal signiert ist, bleibt signiert, geht nur an öffentliche Adressen und folgt keiner Weiterleitung.

Ist die Signatur bei Version-1- und Version-2-Webhooks gleich?

Die Signatur funktioniert gleich. Sie wird über den Body der Zustellung berechnet, egal welches Payload-Format der Webhook nutzt.

Warum sehe ich zwei v1-Werte?

Du hast das Secret vor weniger als 24 Stunden rotiert. Der erste Wert ist mit dem neuen Secret gebildet, der zweite mit dem alten.