Webhooks
Webhooks let you receive real-time notifications when email events occur — delivery, bounce, open, complaint, etc. RelayPost sends an HTTP POST to your endpoint with event details.
Set up a webhook
Section titled “Set up a webhook”Configure webhooks in the RelayPost dashboard under Settings → Webhooks:
- Enter your endpoint URL (e.g.
https://yourapp.com/webhooks/relaypost) - Select the events you want to receive
- Save and copy the signing secret for signature verification
Event types
Section titled “Event types”| Event | Fired when |
|---|---|
queued | Email accepted and added to the delivery queue |
processing | Email is being sent to the recipient’s mail server |
delivered | Email successfully delivered |
opened | Recipient opened the email |
bounced | Recipient’s mail server rejected the email |
deferred | Temporary failure — will retry |
failed | All delivery attempts exhausted |
complained | Recipient marked the email as spam |
rejected | RelayPost rejected the email before sending |
Webhook payload
Section titled “Webhook payload”Each webhook POST contains a JSON body:
{ "event": "delivered", "email_id": "abc123", "message_id": "<uuid@yourapp.com>", "recipient": "user@example.com", "timestamp": "2026-02-13T12:00:00.000Z", "metadata": { "mx_host": "mx.example.com", "smtp_code": 250, "smtp_message": "OK" }}Verifying webhook signatures
Section titled “Verifying webhook signatures”Each webhook request includes a signature header for verification. Validate it to ensure the request came from RelayPost and wasn’t tampered with.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyWebhook(payload, signature, secret) { const expected = createHmac("sha256", secret).update(payload).digest("hex"); return timingSafeEqual( Buffer.from(signature, "utf-8"), Buffer.from(expected, "utf-8"), );}Retry policy
Section titled “Retry policy”If your endpoint returns a non-2xx status code, RelayPost retries the delivery:
- Up to 3 retry attempts
- Exponential backoff between retries
- After all retries fail, the delivery is logged as failed
Best practices
Section titled “Best practices”- Return a
200response quickly — do heavy processing asynchronously - Use webhook signatures to verify authenticity
- Store events idempotently — you may receive the same event more than once
- Monitor your webhook endpoint’s uptime — missed events aren’t replayed automatically