Skip to content
WeZend
CPaaS

Anleitung: WeZend-Webhook-Signaturen in Express verifizieren (mit Code)

Ein vollständiger, funktionierender Express-Endpoint, der Zustell-Webhooks empfängt und alles ablehnt, was nicht wirklich von WeZend stammt.

WWeZend Team5. Juli 2026 · 5 Min. Lesezeit

Die Webhooks von WeZend gelten pro Nachricht: Ihr übergebt webhook_url in der Send-Request selbst (siehe Webhooks) — und das hier ist die Empfängerseite davon.

Der Endpoint

const express = require("express");
const crypto = require("crypto");

const app = express();
app.use(express.raw({ type: "application/json" })); // für die Verifizierung brauchen wir den Raw-Body

app.post("/hooks/wezend", (req, res) => {
  const signature = req.get("X-ZafeConnect-Signature");
  const timestamp = req.get("X-ZafeConnect-Timestamp");
  const rawBody = req.body.toString("utf8");

  const expected = crypto
    .createHmac("sha256", process.env.WEZEND_WEBHOOK_SECRET)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  const isValid =
    signature &&
    expected.length === signature.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));

  if (!isValid) return res.status(401).send("invalid signature");

  res.sendStatus(200); // schnell antworten — die eigentliche Arbeit danach

  const payload = JSON.parse(rawBody);
  processDeliveryEvent(payload).catch(console.error);
});

Drei Dinge, die man richtig machen sollte

  1. Nutzt den Raw-Body für die Signaturprüfung, nicht das geparste/neu serialisierte JSON — beim erneuten Serialisieren können sich Whitespace oder Schlüsselreihenfolge subtil ändern und den HMAC-Vergleich zerstören.
  2. Antwortet mit 2xx, bevor ihr langsame Arbeit erledigt. Eine fehlgeschlagene oder langsame Antwort löst einen Retry aus (30 Sek., 5 Minuten, 30 Minuten) — sinnvoll bei einem echten Ausfall, Verschwendung bei einem Handler, der einfach nur langsam ist.
  3. Die Header-Namen lauten weiterhin X-ZafeConnect-*, nicht X-WeZend-* — ein Überbleibsel des ursprünglichen Plattformnamens, das im Backend noch nicht umbenannt wurde. Übernehmt den Header-Namen exakt wie oben gezeigt; geht nicht davon aus, dass er der aktuellen Marke folgt.

Woher das Signing Secret kommt

Ihr findet (und rotiert) es unter Einstellungen → Webhook-Secret, gestützt auf GET /v1/webhook-secret und POST /v1/webhook-secret/rotate.

Eine Plattform. Jede Kundeninteraktion.

Ersetzen Sie Ihren Flickenteppich aus Messaging-APIs, CDP und Automatisierungstools durch eine Engagement-Plattform, die für Skalierung gebaut ist.

Keine Kreditkarte · EU-Datenhaltung · 99,99 % Uptime-SLA