Auf Events mit Webhooks reagieren
Abonniere WOHNO-Events, verifiziere die HMAC-Signatur und behandle Retries und Re-Delivery von deinem eigenen Endpoint oder einem Automatisierungs-Tool wie Zapier.
Dieser Guide zeigt, wie du Echtzeit-Benachrichtigungen erhältst, wenn sich in WOHNO etwas ändert — eine neue Bewerbung, ein veröffentlichtes Inserat, ein gebuchter Termin — statt zu pollen. Du erstellst eine Webhook-Subscription, verifizierst ihre HMAC-Signatur und behandelst Delivery-Fehler.
Welches Problem das löst: Du möchtest, dass deine Systeme (ein CRM, ein Slack-Channel, ein Zapier-Flow) in dem Moment reagieren, in dem in WOHNO etwas passiert.
Beta / dark-shipped. Die Webhooks-Management-API (Plan 57) ist hinter dem Feature-Flag
WEBHOOKS_PUBLIC_API_ENABLEDgegated; solange es aus ist, liefern diese Endpoints404. Die Operationen sindx-internalund nicht in der öffentlichen Referenz. Bitte deinen WOHNO-Ansprechpartner, sie zu aktivieren.
Voraussetzungen
- Ein Secret Key (
sk_live_…) — das Webhooks-Management ist sk-only. Publishable Keys werden mit403 INSUFFICIENT_SCOPEabgelehnt. - Scope
webhooks:write(impliziertwebhooks:read);webhooks:delete, um Subscriptions zu entfernen. - Ein öffentlicher HTTPS-Endpoint, der
POST-Requests empfangen kann. Die URL wird beim Erstellen SSRF-geprüft, interne/private Adressen werden also abgelehnt.
Schritt 1 — Webhook-Subscription erstellen
Liste die gewünschten Event-Typen unter events (gegen WOHNOs Event-Whitelist
validiert):
curl -X POST https://wohno.de/api/v1/webhooks \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/wohno",
"events": ["listing.published", "application.status_changed", "appointment.booked"],
"description": "Production CRM sync",
"active": true
}'Die 201-Antwort enthält das HMAC-secret — dies ist das einzige Mal,
dass es jemals zurückgegeben wird. Speichere es sicher; du brauchst es, um jede
eingehende Delivery zu verifizieren.
{
"data": {
"id": "wh_1a2b3c4d",
"url": "https://hooks.example.com/wohno",
"events": [
"listing.published",
"application.status_changed",
"appointment.booked"
],
"secret": "whsec_only_shown_once_xxxxxxxx",
"active": true
}
}Wenn du das Secret verlierst, musst du einen neuen Webhook erstellen (oder
rotieren). GET und PATCH geben es nie wieder zurück.
Schritt 2 — Die HMAC-Signatur auf deinem Endpoint verifizieren
Jede Delivery trägt einen X-Webhook-ID- und X-Event-Type-Header sowie eine
X-Webhook-Signature der Form sha256=<hex>. Berechne HMAC-SHA256 über den
rohen Request-Body mit deinem gespeicherten secret und vergleiche in
konstanter Zeit. Lehne alles ab, was nicht übereinstimmt.
// Node.js (Express) — verify before trusting the payload
import crypto from "node:crypto";
const WEBHOOK_SECRET = process.env.WOHNO_WEBHOOK_SECRET; // whsec_…
app.post("/wohno", express.raw({ type: "application/json" }), (req, res) => {
const header = req.get("X-Webhook-Signature") || ""; // "sha256=<hex>"
const signature = header.replace(/^sha256=/, "");
const expected = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(req.body) // raw Buffer, not parsed JSON
.digest("hex");
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) return res.status(401).send("invalid signature");
const event = JSON.parse(req.body.toString());
const type = req.get("X-Event-Type");
const eventId = req.get("X-Webhook-ID"); // use for de-duplication
// Respond fast (2xx) and process asynchronously.
res.status(202).send("ok");
handleEvent(type, eventId, event);
});Verifiziere immer gegen die rohen Bytes — ein erneutes Serialisieren von geparstem JSON kann den Payload verändern und die Signatur brechen.
Schritt 3 — Schnell antworten und Retries arbeiten lassen
Gib einen 2xx-Status zurück, sobald du das Event gespeichert hast; erledige die
eigentliche Arbeit danach. Ist dein Endpoint langsam, wirft Fehler oder liefert
kein 2xx, wiederholt WOHNO die Delivery automatisch.
Schritt 4 — Fehler inspizieren und neu zustellen
Liste die Delivery-Versuche eines Webhooks (offset-paginiert; Payloads und Response-Bodies werden weggelassen, da sie Drittanbieter-Daten enthalten können):
curl "https://wohno.de/api/v1/webhooks/wh_1a2b3c4d/deliveries?status=failed&page=1&per_page=50" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"Eine bestimmte fehlgeschlagene Delivery neu einreihen:
curl -X POST https://wohno.de/api/v1/webhooks/wh_1a2b3c4d/deliveries/dlv_99/redeliver \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"Das liefert 202 mit { "redelivery_id": "...", "status": "pending" }. Ein
409 WEBHOOK_INACTIVE bedeutet, der Webhook ist deaktiviert — aktiviere ihn
zuerst per PATCH wieder.
Zapier oder ein anderes Automatisierungs-Tool nutzen
Richte die Webhook-url auf die Inbound-Webhook-URL des Tools. Kann das Tool
HMAC nicht verifizieren, terminiere die Signaturprüfung in einem schlanken Proxy
unter deiner Kontrolle und leite nur verifizierte Events weiter — vertraue
niemals einem unverifizierten Payload.
Fehlerbehandlung
| Code | HTTP | Was passiert ist | Lösung |
|---|---|---|---|
VALIDATION_ERROR | 400 | Ungültige URL (nicht HTTPS/SSRF) oder unbekanntes Event | Öffentliche HTTPS-URL und whitelistete Events verwenden. |
INSUFFICIENT_SCOPE | 403 | pk_-Key oder webhooks:write fehlt | Secret Key mit dem Scope verwenden. |
NOT_FOUND | 404 | Flag aus, oder Webhook/Delivery nicht deins | Flag und Besitz prüfen. |
WEBHOOK_INACTIVE | 409 | Re-Delivery auf deaktiviertem Webhook | PATCH active: true, dann erneut versuchen. |
Die vollständige Fehlertabelle findest du in der Konventions-Referenz.
Best Practices
- Jede Delivery verifizieren. Ein unverifizierter Payload ist nicht vertrauenswürdiger Input.
- Idempotent sein. Nutze
X-Webhook-IDzur Entduplizierung; Retries können dasselbe Event mehrfach zustellen. - Eng abonnieren. Liste nur die Events, auf die du reagierst.
Nächste Schritte
- Inserate aus deinem CRM synchronisieren — Webhooks mit der Write-API kombinieren.
- Bewerbungen in dein ATS ziehen — auf
application.*-Events reagieren. - API-Referenz — Webhook-Payload-Schemas.