Webhooks
Relay POSTs an event to your endpoint whenever a message is delivered, bounces, or is marked as spam — each one HMAC-signed so you can trust it.
Subscribing
Create a webhook in the console (or via POST /v1/webhooks) with a URL and the events you want (delivery, bounce, complaint). Relay returns a signing secret exactly once— store it.
Event payload
{
"type": "bounce",
"message_id": "msg_2h8Kd0Rk9Qa",
"ses_message_id": "0100018f...",
"recipients": ["ada@lovelace.io"],
"timestamp": 1783386190864
}Verifying the signature
Every delivery carries an X-Webhook-Signature: sha256=<hmac> header — the HMAC-SHA256 of the raw request body under your secret. Compute the same and compare in constant time before trusting the payload.
import crypto from "node:crypto";
export function verify(rawBody, header, secret) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
// constant-time compare
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(header),
);
}
// in your handler:
if (!verify(rawBody, req.headers["x-webhook-signature"], SECRET)) {
return res.status(401).end();
}Return a 2xx quickly. Relay treats non-2xx as a failure and will retry with backoff.