Email Webhooks
Webhooks let Routee push delivery and engagement events to your application in real time — no polling required. For transactional email, webhooks are configured per message using the callback object on the send request.
Prefer to pull instead of push?You can also query the Tracking API (
GET /email/tracking/single/{trackingId}) at any time. Webhooks and the Tracking API report the same events.
Configure callbacks on send
Add a callback object to your POST https://connect.routee.net/transactional-email payload. Routee then POSTs JSON to your HTTPS endpoints as the message progresses.
curl -X POST 'https://connect.routee.net/transactional-email' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"from": { "address": "[email protected]" },
"to": [{ "address": "[email protected]" }],
"subject": "Password reset",
"content": { "html": "<p>Reset your password.</p>" },
"callback": {
"statusCallback": {
"strategy": "OnChange",
"url": "https://your-app.example/webhooks/email-status?token=YOUR_SECRET"
},
"eventCallback": {
"onOpen": "https://your-app.example/webhooks/email-open?token=YOUR_SECRET",
"onClick": "https://your-app.example/webhooks/email-click?token=YOUR_SECRET"
}
}
}'Callback types
| Object | Delivers | Fields |
|---|---|---|
statusCallback | Delivery status transitions | strategy = OnChange (every transition) or OnCompletion (final status only); url |
eventCallback | Engagement events — POST on every open / click that lands | onOpen URL, onClick URL |
Callback strategies
| Strategy | When callbacks fire |
|---|---|
| OnChange | Every delivery status transition. |
| OnCompletion | Only when delivery reaches a final status. |
Delivery status values
Status callbacks carry the same lifecycle values as the tracking timeline:
deliveryStatus | Meaning |
|---|---|
QUEUED | Accepted by Routee; waiting in the mail pipeline |
SENT | Handed off to the recipient mail server |
DELIVERED | Recipient server accepted the message |
BOUNCED | Permanent failure (bad address, policy reject) |
FAILED | Undeliverable after retries |
DEFERRED | Temporary failure; may retry |
A human-readable status accompanies the machine deliveryStatus. Each notification also identifies the message by its trackingId (the id returned by the send request).
Handling webhooks reliably
- Respond fast: return
2xximmediately, then process asynchronously (queue the payload). Slow endpoints may be retried or timed out. - Be idempotent: the same event can be delivered more than once. De-duplicate on
trackingId+ event type + timestamp before acting. - Secure the endpoint: serve over HTTPS and include a hard-to-guess secret in the callback URL (path segment or query string) that you validate on every request. Reject anything without it. Restrict by source IP where possible.
- Expect ordering gaps: events can arrive out of order (e.g. an open before the delivered status). Rely on
timestamp, not arrival order.
Step-by-stepSee the tutorial Receive transactional email delivery callbacks for an end-to-end receiver.
Next steps
- Email tracking, statuses & callbacks — full status list and the pull-based Tracking API
- Send a transactional email — the
callbackobject reference - Callback Object Explained · Status Callback Object Explained
Callback retry policy
Your endpoint must respond with HTTP 200 OK within 2 seconds. Otherwise Routee closes the connection and retries (up to 12 attempts over 24 hours).
| Attempt | Delay after previous try |
|---|---|
| 1st | 30 sec |
| 2nd | 1 min |
| 3rd | 2 min |
| 4th | 5 min |
| 5th | 10 min |
| 6th | 15 min |
| 7th | 30 min |
| 8th | 1 hour |
| 9th | 2 hours |
| 10th | 4 hours |
| 11th | 8 hours |
| 12th | 24 hours |
Design your handler to be idempotent — the same event may be delivered more than once.
Updated 2 days ago

