API reference
Webhook events
The payloads Deckle delivers to your registered webhook endpoints.
When something happens to an email you sent, Deckle POSTs a signed event to every active webhook endpoint subscribed to that event type.
Request format#
Every delivery is an HTTP POST with a JSON body and two headers: X-Deckle-Event (the event type) and X-Deckle-Signature (an HMAC-SHA256 hex digest of the raw body — see Verifying signatures).
http
POST /your/webhook HTTP/1.1
Content-Type: application/json
X-Deckle-Event: email.delivered
X-Deckle-Signature: 3f9a1c...e7Envelope#
Every event shares the same top-level shape:
json
{
"type": "email.delivered",
"created_at": "2026-07-10T14:23:45.123Z",
"data": { }
}Event types#
| type | Fired when |
|---|---|
email.delivered | The receiving mail server accepted the message. |
email.bounced | A hard bounce. The address is also added to your suppression list. |
email.complained | The recipient marked it as spam. The address is suppressed. |
email.opened | The tracking pixel was loaded. |
email.clicked | A tracked link was clicked. |
The data object#
The data object identifies the email the event is about — its id, recipient, and subject — plus fields specific to the event.
email.delivered / opened#
json
{
"type": "email.opened",
"created_at": "2026-07-10T14:25:00.000Z",
"data": {
"id": "email_9f2c1a8b",
"to": "jane@example.com",
"subject": "Welcome to Acme"
}
}email.clicked#
Click events also include the url that was followed.
json
{
"type": "email.clicked",
"created_at": "2026-07-10T14:26:10.000Z",
"data": {
"id": "email_9f2c1a8b",
"to": "jane@example.com",
"subject": "Welcome to Acme",
"url": "https://acme.com/get-started"
}
}email.bounced / complained#
json
{
"type": "email.bounced",
"created_at": "2026-07-10T14:24:30.000Z",
"data": {
"id": "email_9f2c1a8b",
"to": "jane@example.com",
"subject": "Welcome to Acme",
"reason": "hard_bounce"
}
}Always respond 2xx quickly
Acknowledge the webhook with a2xx status as soon as you’ve verified the signature, then do slow work asynchronously. Verify the signature against the raw body before trusting any field.