Documentation

Webhooks

Subscribe to real-time events — delivery, bounces, complaints, opens and clicks — instead of polling. Create an endpoint under Developers → Webhooks.

Events

Email

Domain & contact

Delivery headers

Every webhook POST carries these headers:

HeaderValue
X-Mailstein-EventThe event type, e.g. email.delivered.
X-Mailstein-CallUnique ID for this delivery attempt.
X-Mailstein-TimestampUnix-ms time the request was signed.
X-Mailstein-Signaturev1=<hmac-sha256-hex> over timestamp + body.
X-Mailstein-Retrytrue if this is a redelivery.

Verify the signature

Compute an HMAC-SHA256 of timestamp + "." + rawBody with your endpoint's signing secret and compare, in constant time, against X-Mailstein-Signature.

Node.js
import crypto from "crypto";

function verify(rawBody, headers, secret) {
  const ts = headers["x-mailstein-timestamp"];
  const sig = headers["x-mailstein-signature"];
  const expected = "v1=" + crypto
    .createHmac("sha256", secret)
    .update(ts + "." + rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
The Node SDK ships a Webhooks helper that does this for you. Always verify before trusting a payload, and respond 2xx quickly — non-2xx responses are retried (watch X-Mailstein-Retry to stay idempotent).