Email callback payloads

Delivery and engagement webhook JSON — field reference and examples for Connect HTTP send.

Email callback payloads

Reference for the JSON Routee POSTs to your webhook URLs when you configure callback on POST /transactional-email on Connect.

Setup first: Receive transactional email delivery callbacks — how to register statusCallback and eventCallback URLs, retry rules, and firewall notes.


Overview

On https://connect.routee.net/transactional-email, Routee delivers callbacks as a JSON object with batchId, messageId, status, results[], and optional reason (failures) or click (engagement).

SMTP relay does not use these webhooks — use Search email tracking or portal logs instead.


Configure on send (reminder)

{
  "from": { "address": "[email protected]" },
  "to": [{ "address": "[email protected]" }],
  "subject": "Order shipped",
  "content": { "html": "<p>Your order is on the way.</p>" },
  "callback": {
    "statusCallback": {
      "strategy": "OnChange",
      "url": "https://partner.example/webhooks/email-status"
    },
    "eventCallback": {
      "onOpen": "https://partner.example/webhooks/email-open",
      "onClick": "https://partner.example/webhooks/email-click"
    }
  }
}
Send-time fieldUsed for
statusCallbackDelivery lifecycle (QUEUED, DELIVERED, BOUNCED, …)
eventCallback.onOpen / onClickEngagement (OPENED, CLICKED)

strategy: OnChange (every transition) or OnCompletion (terminal delivery only). Applies to status callbacks.


Identifiers

FieldWhereMeaning
trackingIdSend responseBatch id for the send — use with Get email tracking (batch summary)
batchIdCallback payloadSame value as trackingId
messageIdCallback payloadPer-recipient id — use with Get email tracking (recipient timeline)

Multi-recipient sends: one trackingId / batchId, many messageId values.


Delivery status (statusCallback.url)

Routee POSTs a JSON object to your status URL. Top-level status values include:

QUEUED, SENT, DIFFERED, DELIVERED, BOUNCED, FAILED, UNDELIVERED

Common fields

FieldTypeDescription
batchIdstringBatch tracking id (send response trackingId)
messageIdstringPer-recipient message id
createdAt, updatedAtstring (ISO-8601)Timestamps
statusstringCurrent delivery status (see enum above)
from, tostringEnvelope addresses
senderstringFrom address (email)
subjectstringSubject line (max 144 chars when present)
cc, labelstringOptional
results[]arrayStatus history — each item has updatedAt, status
customHeaders[]arrayOptional { name, value } pairs
reasonobjectOptional on failure/bounce — see below

reason (failures & bounces)

Present when diagnostic detail is available:

FieldDescription
descriptionHuman-readable SMTP or processing message
codeProvider or internal code when available
deliveryStatusUnderlying delivery status string
dsnParsed DSN map when available

Example — delivered

{
  "batchId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "507f1f77bcf86cd799439011",
  "createdAt": "2026-07-14T08:15:00Z",
  "updatedAt": "2026-07-14T08:16:22Z",
  "status": "DELIVERED",
  "from": "[email protected]",
  "to": "[email protected]",
  "sender": "[email protected]",
  "subject": "Order shipped",
  "results": [
    {
      "updatedAt": "2026-07-14T08:15:01Z",
      "status": "QUEUED"
    },
    {
      "updatedAt": "2026-07-14T08:16:22Z",
      "status": "DELIVERED"
    }
  ],
  "customHeaders": []
}

Example — bounced (with reason)

{
  "batchId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "507f1f77bcf86cd799439011",
  "createdAt": "2026-07-14T08:15:00Z",
  "updatedAt": "2026-07-14T08:17:05Z",
  "status": "BOUNCED",
  "from": "[email protected]",
  "to": "[email protected]",
  "sender": "[email protected]",
  "subject": "Order shipped",
  "results": [
    {
      "updatedAt": "2026-07-14T08:17:05Z",
      "status": "BOUNCED"
    }
  ],
  "reason": {
    "description": "550 5.1.1 User unknown",
    "code": "550",
    "deliveryStatus": "BOUNCED",
    "dsn": {
      "action": "failed",
      "status": "5.1.1"
    }
  }
}

Engagement (eventCallback.onOpen / onClick)

Routee POSTs a JSON object to the URL you configured for the event. Top-level status: OPENED or CLICKED.

Shares the same envelope fields as status callbacks (batchId, messageId, from, to, sender, subject, results[], …).

click (CLICKED only)

FieldDescription
urlOriginal long URL
shortUrlTracked short URL when present
ip, country, cityGeo / network hints when available
referrer, device, browserClient hints when available
lagMilliseconds from send to click
clickedAtTimestamp string

Example — opened

{
  "batchId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "507f1f77bcf86cd799439011",
  "createdAt": "2026-07-14T08:15:00Z",
  "updatedAt": "2026-07-14T08:20:11Z",
  "status": "OPENED",
  "from": "[email protected]",
  "to": "[email protected]",
  "sender": "[email protected]",
  "subject": "Order shipped",
  "results": [
    {
      "updatedAt": "2026-07-14T08:20:11Z",
      "status": "OPENED"
    }
  ]
}

Example — clicked

{
  "batchId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "507f1f77bcf86cd799439011",
  "createdAt": "2026-07-14T08:15:00Z",
  "updatedAt": "2026-07-14T08:21:44Z",
  "status": "CLICKED",
  "from": "[email protected]",
  "to": "[email protected]",
  "sender": "[email protected]",
  "subject": "Order shipped",
  "results": [
    {
      "updatedAt": "2026-07-14T08:21:44Z",
      "status": "CLICKED"
    }
  ],
  "click": {
    "url": "https://shop.example.com/orders/12345",
    "shortUrl": "https://w.sends.ms/abc123",
    "ip": "203.0.113.10",
    "country": "GR",
    "city": "Athens",
    "lag": 404000,
    "clickedAt": "2026-07-14T08:21:44Z"
  }
}

Engagement webhook deduplication

To avoid duplicate notifications while still recording every engagement internally:

EventWebhook ruleInternal tracking
OpenAt most one open webhook per message/recipientEvery open increments openedCount in logs
ClickAt most one click webhook per message/recipient per URLEvery click increments clickCount in logs

Repeat clicks on the same link are counted in Search email tracking but do not emit duplicate webhooks.


Handler checklist

  1. Accept POST with Content-Type: application/json
  2. Return HTTP 200 within 2 seconds (platform retry policy applies — see Receive transactional email delivery callbacks)
  3. Ignore unknown JSON fields for forward compatibility
  4. Correlate using trackingId from your send response — match callback batchId
  5. For per-recipient logic on multi-recipient sends, use callback messageId or poll tracking APIs

Firewall

Whitelist inbound traffic from callbacksallow.routee.net on your callback URLs.


Related