Webhooks
Webhooks
Get notified in real time when your emails are delivered, bounced, opened, clicked, or complained about — Deckle POSTs each event to an endpoint you control.
Instead of polling the API for the status of every send, register an HTTPS endpoint and let Deckle push events to you as they happen. Each delivery is a signed POST you can verify and act on — sync a database, alert a channel, or trigger downstream work.
What are webhooks#
A webhook is an HTTPS URL you own that Deckle sends events to. Whenever something happens to an email you sent — it’s delivered, it bounces, a recipient opens or clicks it, or someone marks it as spam — Deckle makes an HTTP POST request to your endpoint with a JSON body describing the event.
Your endpoint responds with a 2xx status to acknowledge receipt. Because the request originates from Deckle and not from a browser session, every delivery is signed so you can confirm it’s genuine before you trust it. See Verify signatures for how to check the signature.
HTTPS only
Endpoints must usehttps://. Deckle will not deliver events to plaintext HTTP URLs.Register an endpoint#
Add and manage endpoints from the dashboard. Each project has its own webhook endpoints, and each endpoint subscribes to the specific event types you care about.
Open Developers → Webhooks
app.getdeckle.com, go to Developers and open the Webhooks section.Add your HTTPS URL and choose events
https://api.acme.com/webhooks/deckle), and select which event types this endpoint should receive.Copy the signing secret
whsec_...) once, at creation. Copy it and store it securely — you’ll need it to verify incoming requests, and it’s never shown again.The signing secret is shown once
Store yourwhsec_... secret in a secure place right away. If you lose it, rotate the secret from the dashboard to generate a new one.The payload#
Every delivery is a POST with a JSON body containing the event type, an ISO 8601 created_at timestamp, and a data object with the details for that event.
{
"type": "email.delivered",
"created_at": "2026-07-10T18:24:05.123Z",
"data": {
"id": "email_9fQ2xk7Lp",
"to": "jane@example.com",
"subject": "Welcome to Acme 👋"
}
}Each request also carries two headers you’ll want to read:
| Header | Description |
|---|---|
X-Deckle-Signature | HMAC-SHA256 of the raw request body, hex-encoded, computed with your endpoint’s whsec_... secret. Use it to verify authenticity. |
X-Deckle-Event | The event type, mirroring type in the body — handy for routing before you parse the payload. |
Verify against the raw body
Compute the signature over the exact bytes Deckle sent — the raw request body, before any JSON parsing or re-serialization. See Verify signatures for a copy-paste example usingverifyWebhookSignature from @deckle/sdk.Event types#
Endpoints can subscribe to any combination of the following event types. The canonical data schema for each one is documented on Event types.
email.delivered— the message was accepted by the recipient’s mail server.email.bounced— the message could not be delivered; hard bounces are auto-suppressed.email.complained— the recipient marked the message as spam; the address is auto-suppressed.email.opened— the recipient opened the message (tracked sends only).email.clicked— the recipient clicked a link;dataincludes theurl.
Delivery#
Deckle delivers each event on a best-effort basis to every active endpoint subscribed to that event type. An endpoint that’s disabled, or not subscribed to the event, is skipped. To keep receiving events, respond with a 2xx status quickly and do any heavy processing asynchronously.
You don’t need real traffic to check your integration. From the dashboard, send a test.ping event to any endpoint to confirm it’s reachable and that your signature verification works end to end.
Test before you go live
Use thetest.ping button on the endpoint in the dashboard to fire a sample delivery, then confirm your handler returns 2xx and the signature validates.