Webhook events
The email.sent, email.opened, and email.clicked events — envelope and per-event payload shapes, generated from the live fan-out's schemas.
Webhook events
Batohi delivers three event types. The envelope is the same for every event;
the data payload varies by type. The schemas below are generated from the same
WEBHOOK_PAYLOAD_SCHEMAS the live fan-out validates against, so they cannot
drift from what is delivered.
Envelope
Every delivery is a JSON body with this shape:
Envelope
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Deterministic delivery id — use for idempotent dedup. |
| type | string | yes | The event type. |
| timestamp | string | yes | Delivery-attempt time (ISO 8601). NOT the original event time — that is in data.*At. |
| data | object | yes | Event-specific payload. See the per-event schemas. |
timestampis the delivery-attempt time, not the event time. It is recomputed on each retry. The original engagement-event time lives only insidedata.openedAt/data.clickedAt/data.sentAt. Do not treat the envelopetimestampas when the open/click/send happened.
email.sent
Fired when a message is sent.
data — email.sent
| Field | Type | Required | Description |
|---|---|---|---|
| trackId | string | yes | The tracked message identifier. |
| recipientCount | integer | null | yes | Number of recipients, or null if unknown. |
| sentAt | string | null | yes | ISO 8601 send timestamp, or null. |
email.opened
Fired only for genuine opens. A proxy prefetch, self-open, or scanner does not fire this event.
data — email.opened
| Field | Type | Required | Description |
|---|---|---|---|
| trackId | string | yes | The tracked message identifier. |
| openedAt | string | yes | ISO 8601 timestamp of the genuine open. |
email.clicked
Fired when a tracked link is clicked. linkId is null when the click can't be
attributed to a specific rewritten link.
data — email.clicked
| Field | Type | Required | Description |
|---|---|---|---|
| trackId | string | yes | The tracked message identifier. |
| linkId | string | null | yes | The clicked link identifier, or null if unavailable. |
| clickedAt | string | yes | ISO 8601 timestamp of the click. |
Idempotency
The id field is deterministic: ${outboxEventId}_${endpointId}. A redelivered
outbox event never double-queues — use id as your dedup key.