Overview
When you set up webhooks, an HTTP POST request is sent to the specified URL whenever events such as email sending, opens, or clicks occur.
Webhooks can be configured in Dashboard > Webhooks.
Event Types
| Event | Description |
|---|---|
email.sent |
When an email is sent |
email.delivered |
When an email is delivered to the recipient |
email.opened |
When a recipient opens an email |
email.clicked |
When a recipient clicks a link in an email |
email.bounced |
When an email bounces |
email.complained |
When a recipient reports the email as spam |
subscriber.created |
When a new subscriber is added |
subscriber.unsubscribed |
When a subscriber unsubscribes |
campaign.sent |
When a campaign sending starts |
campaign.completed |
When a campaign sending is completed |
Payload Format
All webhook requests include a JSON payload in the following format:
{
"event": "email.opened",
"timestamp": "2026-01-10T12:00:00+00:00",
"data": {
"campaign_id": 123,
"campaign_uuid": "abc-123...",
"campaign_name": "January Newsletter",
"subscriber_id": 456,
"subscriber_uuid": "def-456...",
"subscriber_email": "user@example.com",
"ip_address": "1.2.3.4",
"user_agent": "Mozilla/5.0...",
"occurred_at": "2026-01-10T12:00:00+00:00"
}
}
Request Headers
| Header | Description |
|---|---|
Content-Type |
application/json |
X-Webhook-ID |
Webhook UUID |
X-Webhook-Event |
Event type (e.g. email.opened) |
X-Webhook-Signature |
HMAC-SHA256 signature |
Signature Verification
Verify the X-Webhook-Signature header to confirm the authenticity of webhook requests. The signature is an HMAC-SHA256 hash using the webhook secret and the request body.
PHP Example
<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$secret = 'your_webhook_secret';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
die('Invalid signature');
}
$data = json_decode($payload, true);
// Process the event...
Node.js Example
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Express.js example
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
if (!verifySignature(payload, signature, 'your_secret')) {
return res.status(401).send('Invalid signature');
}
// Process the event...
res.status(200).send('OK');
});
Retry Policy
- • If a webhook delivery fails (non-2xx response), it will not be automatically retried.
- • After 5 consecutive failures, the webhook is automatically deactivated.
- • Deactivated webhooks can be re-enabled from the dashboard.
- • Response time must be within 10 seconds.
Best Practices
- • Always verify the signature to confirm the authenticity of requests.
- • Process webhooks as quickly as possible (within 5 seconds).
- • Queue long-running tasks and return 200 OK immediately.
- • Use HTTPS endpoints to transmit data securely.