Webhooks
Configure a webhook URL per verified sender domain to receive real-time HTTP POST callbacks when email events occur. Configure from the Domains page under the Webhook button on any verified domain.
| Event | Fired when |
|---|---|
email.sent | Message accepted by our mail server |
email.delivered | Message delivered to recipient mail server |
email.bounced | Message permanently rejected (hard bounce) |
Payload shape
{
"event": "email.delivered",
"messageId": "71688732-3522-48fe-a86a-b3bdd19540ae",
"timestamp": 1716163741,
"data": {
"recipientEmail": "user@example.com",
"senderDomain": "yourdomain.com"
}
}Verifying the signature
Every request includes an X-Altermail-Signature header. Verify it using the signing secret shown in the Domains page after saving your webhook.
const crypto = require("crypto");
function verifyWebhook(rawBody, signature, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return expected === signature;
}
// In your Express handler:
app.post("/webhook", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.headers["x-altermail-signature"];
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body);
console.log(event.event, event.messageId);
res.sendStatus(200);
});Webhook delivery notes
- •Webhooks time out after 3 seconds. Return a 2xx quickly and process async.
- •Failed webhook deliveries are not retried. Use the events API as a fallback.
- •You can select which event types to receive per domain.