Webhooks

Receive real-time notifications when email events occur.

Overview

Webhooks allow you to receive HTTP POST requests when events like email delivery, opens, clicks, and bounces occur. This enables real-time tracking and automation.

Creating a webhook

Create a webhook endpoint to receive events:

// POST /api/webhooks
{
    "url": "https://yourapp.com/webhooks/sentd",
    "events": ["email.delivered", "email.opened", "email.bounced"],
    "description": "Production webhook"
}

Available events

EventDescription
email.sentEmail was sent to the provider
email.deliveredEmail was delivered to recipient
email.openedRecipient opened the email
email.clickedRecipient clicked a link
email.bouncedEmail bounced (hard or soft)
email.complainedRecipient marked as spam
email.unsubscribedRecipient unsubscribed

Webhook payload

Each webhook request includes the event data:

{
    "id": "evt_abc123",
    "type": "email.delivered",
    "created_at": "2024-01-15T10:30:00Z",
    "data": {
        "email_id": "em_xyz789",
        "to": "user@example.com",
        "subject": "Welcome!",
        "delivered_at": "2024-01-15T10:30:00Z"
    }
}

Verifying webhooks

Verify webhook signatures to ensure requests are from SENTD:

import crypto from 'crypto';

function verifyWebhook(payload, signature, secret) {
    const expected = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expected)
    );
}

// In your webhook handler
app.post('/webhooks/sentd', (req, res) => {
    const signature = req.headers['x-sentd-signature'];
    const isValid = verifyWebhook(
        JSON.stringify(req.body),
        signature,
        process.env.WEBHOOK_SECRET
    );

    if (!isValid) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    // Process the webhook
    console.log('Event:', req.body.type);
    res.json({ received: true });
});

Always verify webhook signatures in production to prevent spoofing attacks.

Retry policy

If your endpoint returns a non-2xx status, we'll retry with exponential backoff:

  • Retry 1: After 1 minute
  • Retry 2: After 5 minutes
  • Retry 3: After 30 minutes
  • Retry 4: After 2 hours
  • Retry 5: After 24 hours (final)