Signed delivery webhooks
Connect delivery events to your application without continuously polling.
Register a public HTTPS endpoint
Create a webhook from the dashboard with an HTTPS URL you control. Endpoint setup uses a dashboard session. All delivery events are forwarded to each enabled endpoint; per-event subscription filters are not supported. Private, loopback, link-local, and other unsafe network targets are rejected. Save the signing secret when shown.
Verify before processing
Validate the HMAC against the exact raw request body and timestamp before parsing JSON or taking business actions. Use a constant-time comparison and reject stale timestamps. See the signature contract below.
Signature contract and Node.js verification
Headers are x-notifications-event-id, x-notifications-timestamp (Unix seconds), and x-notifications-signature (v1= followed by hex HMAC-SHA256). Sign the timestamp, a period, and the raw UTF-8 body using your displayed signing secret. This verifier allows five minutes of clock skew. Deduplicate the event ID after verification.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyWebhook(rawBody, timestamp, signature, secret) {
if (!/^\d+$/.test(timestamp || "")) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (!/^v1=[a-f0-9]{64}$/.test(signature || "")) return false;
const expected = createHmac("sha256", secret)
.update(timestamp + ".").update(rawBody).digest();
const received = Buffer.from(signature.slice(3), "hex");
return received.length === expected.length && timingSafeEqual(received, expected);
}
// rawBody must be the original Buffer, before JSON body parsing.
// Return 2xx only after persisting the verified event for processing.Retries and duplicate events
Return a 2xx response promptly after durable acceptance in your own system. Webhook delivery is retried on failures. Treat events as potentially duplicated and out of order; use event IDs for deduplication and avoid regressing terminal states.
Inspect delivery attempts
The dashboard shows callback delivery attempts so you can investigate an endpoint failure separately from email delivery. A callback failure does not mean the underlying email failed.