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

ObjectDeliversFields
statusCallbackDelivery status transitionsstrategy = OnChange (every transition) or OnCompletion (final status only); url
eventCallbackEngagement events — POST on every open / click that landsonOpen URL, onClick URL

Callback strategies

StrategyWhen callbacks fire
OnChangeEvery delivery status transition.
OnCompletionOnly when delivery reaches a final status.

Delivery status values

Status callbacks carry the same lifecycle values as the tracking timeline:

deliveryStatusMeaning
QUEUEDAccepted by Routee; waiting in the mail pipeline
SENTHanded off to the recipient mail server
DELIVEREDRecipient server accepted the message
BOUNCEDPermanent failure (bad address, policy reject)
FAILEDUndeliverable after retries
DEFERREDTemporary 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 2xx immediately, 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-step

See the tutorial Receive transactional email delivery callbacks for an end-to-end receiver.

Next steps

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).

AttemptDelay after previous try
1st30 sec
2nd1 min
3rd2 min
4th5 min
5th10 min
6th15 min
7th30 min
8th1 hour
9th2 hours
10th4 hours
11th8 hours
12th24 hours

Design your handler to be idempotent — the same event may be delivered more than once.

Secure your endpoint — Serve callbacks over HTTPS and include a hard-to-guess secret in the callback URL path or query string. Validate it on every request.