Ein Webhook sendet die Entscheidungen bot und bot_high von Bot Protection an einen Endpoint von Ihnen: die Weiterleitung in einen Chat-Kanal, eine Ticket-Warteschlange, Ihre eigene Betrugsprüfung. Ihr Server erhält jede Entscheidung weiterhin von /v1/decide wie bisher; der Webhook ist eine Kopie, nach der Antwort gesendet, und lässt keine Entscheidung warten.
Endpoint festlegen
Auf der Seite Einrichtung des Dashboards, unter Webhook, schreibt ein Inhaber die Adresse des Endpoints und wählt, was er erhält:
- Jede Entscheidung der gewählten Klassen,
bot,bot_highoder beide, in Stapeln von bis zu 100, Sekunden nach der Entscheidung. - Eine Zusammenfassung alle 5, 15 oder 60 Minuten: wie viele Entscheidungen
botundbot_highes gab.
Die Adresse beginnt mit https://, auf Port 443, mit einem Namen wie hooks.example.com, nie mit einer IP-Adresse. Korzen sendet nichts an eine Adresse eines privaten Netzes, worauf der Name auch auflöst, und prüft das bei jeder Zustellung.
Wenn ein Endpoint zum ersten Mal gespeichert wird, zeigt die Einrichtung sein Signing Secret, kz_whs_ und 64 Zeichen, ein einziges Mal: Kopieren Sie es in die Konfiguration Ihres Endpoints. Neues Secret erstellen ersetzt es, ebenfalls nur einmal angezeigt; 24 Stunden lang signiert das alte jede Zustellung noch mit, damit Ihr Endpoint weiter prüft, während Sie seine Kopie aktualisieren. Test senden sendet jetzt eine signierte Zustellung test und zeigt, was Ihr Endpoint antwortete.
Der Payload
Jede Zustellung ist ein POST mit einem JSON-Body. Ein Stapel von Entscheidungen:
{
"type": "decisions",
"id": "0193a5f0-7c1e-7d2a-9b4e-3f1a2c9d8e01",
"decisions": [
{
"at": "2026-10-28T12:00:00.123Z",
"request_id": "…",
"class": "bot_high",
"action": "block",
"intended_action": "block",
"bot_score": 97,
"mode": "block",
"reasons": ["behaviour", "inconsistency"]
}
],
"dropped": 0
}
Jede Entscheidung ist at, der Zeitpunkt der Entscheidung, und diese Mitglieder der Antwort, die /v1/decide Ihrem Server gab: request_id, class, bot_score, human_score, reasons, action, intended_action, mode, step_up, token_required, identity_limited, seen_before, crawler, decoy und own_server. Sonst nichts: nie der Name einer Regel, der context, den Sie gesendet haben, oder der Link der Challenge-Seite. dropped zählt die Entscheidungen, für die dieser Stapel keinen Platz hatte.
Eine Zusammenfassung:
{"type": "summary", "id": "…", "from": "2026-10-28T12:00:00Z", "to": "2026-10-28T12:15:00Z", "bot": 412, "bot_high": 37}
Ein Test: {"type": "test", "id": "…", "at": "…"}. Lesen Sie zuerst type: Ein neuer Typ kann hinzukommen, und jedem kann ein Feld hinzugefügt werden.
id ist bei jedem Versuch einer Zustellung dieselbe: Haben Sie sie schon verarbeitet, antworten Sie mit 2xx und verwerfen Sie sie. Zustellungen können in anderer Reihenfolge ankommen.
Was eine Zustellung verspricht
- Mindestens einmal, sobald eingereiht. Eine eingereihte Zustellung wird versucht, bis Ihr Endpoint mit
2xxantwortet oder pausiert wird; dieselbe Zustellung kann also zweimal kommen: Verwerfen Sie eine Wiederholung anhand ihrerid. - Best Effort davor. Jeder Server von Korzen hält eine Entscheidung bis zu 10 Sekunden, bevor er sie einreiht, und reiht alles ein, was er hält, wenn er für ein Deploy stoppt. Ein Server, der abstürzt, verliert, was er hielt, und die Entscheidungen über den Platz eines Stapels oder das Stundenlimit Ihres Plans hinaus werden in
droppedgezählt, nie gesendet. - Der Webhook ist eine Kopie, nicht der Nachweis. Jede Entscheidung bleibt auf der Seite Entscheidungen des Dashboards, die auch die Werkzeuge
list_decisionsundget_decisiondes MCP-Servers lesen: Suchen Sie eine Entscheidung dort anhand ihrerrequest_id.
Die Signatur prüfen
Jede Zustellung trägt Korzen-Signature: t=<Unix-Sekunden>,v1=<hex>: den HMAC-SHA256, unter Ihrem Signing Secret, von t, einem Punkt und dem Body genau so, wie er ankam. Berechnen Sie ihn über die rohen Bytes, vor jedem JSON-Parsing, vergleichen Sie in konstanter Zeit, und lehnen Sie ein t ab, das mehr als 5 Minuten von Ihrer Uhr abweicht, damit eine einmal aufgezeichnete Zustellung später nicht erneut gesendet werden kann. 24 Stunden nach einem neuen Secret folgt ein zweites v1, unter dem alten: Nehmen Sie eine Zustellung an, wenn irgendein v1 passt.
import { createHmac, timingSafeEqual } from "node:crypto"; // raw: the body as received (a Buffer); header: Korzen-Signature function verify(raw, header, secret) { const parts = header.split(",").map((p) => p.split("=")); const t = Number(parts.find(([k]) => k === "t")?.[1]); if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300) return false; const mac = createHmac("sha256", secret).update(`${t}.`).update(raw).digest(); return parts.some(([k, v]) => { const got = Buffer.from(k === "v1" ? v ?? "" : "", "hex"); return got.length === mac.length && timingSafeEqual(got, mac); }); }
import hashlib, hmac, time def verify(raw: bytes, header: str, secret: str) -> bool: parts = [p.partition("=")[::2] for p in header.split(",")] t = next((v for k, v in parts if k == "t"), "") if not t.isdigit() or abs(time.time() - int(t)) > 300: return False mac = hmac.new(secret.encode(), f"{t}.".encode() + raw, hashlib.sha256).hexdigest() return any(k == "v1" and hmac.compare_digest(mac, v) for k, v in parts)
Antwort und Wiederholungen
Antworten Sie innerhalb von 5 Sekunden mit einem beliebigen 2xx: Der Body wird nicht gelesen. Alles andere, auch eine Weiterleitung, oder keine rechtzeitige Antwort, ist ein Fehlschlag, und die Zustellung wird 30 Sekunden später erneut versucht, danach jeweils nach doppelt so langer Zeit, 8 Versuche in etwa einer Stunde. Erledigen Sie langsame Arbeit nach der Antwort.
Solange Ihr Endpoint fehlschlägt, warten neue Entscheidungen, bis zu 100, und der Rest wird in dropped gezählt. Ein Endpoint, der eine Stunde lang fehlschlägt, wird pausiert: Es wird nichts an ihn gesendet, die Entscheidungen in der Zwischenzeit werden nicht gesendet, und jeder Inhaber erhält eine E-Mail. Die Einrichtung zeigt den Status oder den Fehler der letzten Zustellung; Fortsetzen sendet ab der nächsten Entscheidung wieder.
Limits
Jeder Plan sendet bis zu einer Anzahl Entscheidungen pro Stunde: die kostenlose Testphase 1.000, Starter 10.000, Pro 50.000, Scale 200.000. Darüber hinaus werden die Entscheidungen im dropped des nächsten Stapels gezählt, und die nächste Stunde beginnt neu. Eine Zusammenfassung wird immer gesendet. Ein Webhook zählt nicht zu Ihren monatlichen Entscheidungen.