Webhooks

Webhooks allow you to receive real-time notifications when events occur in your Broadcast account, such as when emails are sent, opened, or when subscribers are added or removed.

What are Webhooks?

Webhooks are HTTP callbacks that Broadcast sends to your application when specific events occur. Instead of repeatedly checking for updates, your application can receive instant notifications when something happens.

Common use cases for webhooks include:

  • Syncing subscriber data with your CRM
  • Updating analytics dashboards in real-time
  • Triggering automated workflows based on email interactions
  • Logging email events for compliance purposes

Available Event Types

Broadcast supports the following webhook event types:

Email Events

  • email.sent - Email was successfully sent
  • email.delivered - Email was delivered to the recipient’s inbox
  • email.delivery_delayed - Email delivery was delayed
  • email.bounced - Email bounced (hard or soft bounce)
  • email.complained - Recipient marked email as spam
  • email.opened - Recipient opened the email
  • email.clicked - Recipient clicked a link in the email
  • email.failed - Email failed to send

Subscriber Events

  • subscriber.created - New subscriber was added
  • subscriber.updated - Subscriber information was updated
  • subscriber.deleted - Subscriber was deleted
  • subscriber.subscribed - Subscriber opted in or was reactivated
  • subscriber.unsubscribed - Subscriber opted out
  • subscriber.bounced - Subscriber email bounced
  • subscriber.complained - Subscriber marked email as spam

System Events

  • message.attempt.exhausted - All delivery attempts failed
  • test.webhook - Test webhook event

Setting Up Webhooks

To set up a webhook endpoint:

  1. Go to Webhook Endpoints in your Broadcast dashboard sidebar
  2. Click Add Webhook Endpoint
  3. Enter your webhook URL (must be HTTPS)
  4. Select the event types you want to receive
  5. Optionally add a description
  6. Click Create Webhook Endpoint

HTTPS Required

Webhook URLs must use HTTPS for security. HTTP URLs will be rejected.

Webhook Payload Structure

All webhook payloads follow this structure:

{
  "id": 123,
  "type": "email.sent",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    // Event-specific data
  }
}

Email Event Payload Example

{
  "id": 123,
  "type": "email.opened",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "receipt_id": 456,
    "email": "[email protected]",
    "identifier": "unique-email-id",
    "opened_at": "2024-01-15T10:30:00Z",
    "delivered": true,
    "opened": true,
    "clicked": false,
    "bounced": false,
    "complaint": false,
    "unsubscribed": false
  }
}

Subscriber Event Payload Example

{
  "id": 789,
  "type": "subscriber.created",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "subscriber_id": 101,
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "subscribed_at": "2024-01-15T10:30:00Z",
    "unsubscribed_at": null,
    "is_active": true,
    "custom_data": {
      "company": "Example Corp"
    },
    "source": "api"
  }
}

Webhook Security

Broadcast signs all webhook payloads using HMAC-SHA256 to ensure authenticity. You should verify the signature before processing webhook events.

Signature Verification

Each webhook request includes these headers:

  • broadcast-webhook-id - Unique identifier for the webhook event
  • broadcast-webhook-timestamp - Unix timestamp when the webhook was sent
  • broadcast-webhook-signature - HMAC signature for verification

The signature is calculated using:

HMAC-SHA256(timestamp + "." + payload, webhook_secret)

Example Verification (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, headers, secret) {
  const signature = headers['broadcast-webhook-signature'];
  const timestamp = headers['broadcast-webhook-timestamp'];

  // Check timestamp to prevent replay attacks (within 5 minutes)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > 300) {
    return false;
  }

  // Calculate expected signature
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('base64');

  // Extract signature from header (format: "v1,signature")
  const actualSignature = signature.split(',')[1];

  // Compare signatures
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(actualSignature)
  );
}

Delivery and Retries

Broadcast implements a robust retry mechanism for webhook deliveries:

  • Retry Schedule: 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours
  • Success Criteria: HTTP status codes 200-299
  • Timeout: 30 seconds per request
  • Exhausted Events: After all retries fail, a message.attempt.exhausted event is sent

Monitoring Webhook Deliveries

You can monitor webhook delivery status in the dashboard:

  1. Go to Webhook Endpoints
  2. Click on your webhook endpoint
  3. View delivery logs, success rates, and error messages
  4. Check recent deliveries and their response codes

Testing Webhooks

Broadcast provides several ways to test your webhook endpoints:

Test Webhook Button

Click the Test Webhook button on any webhook endpoint to send a test event immediately.

Using webhook.site

For development, you can use webhook.site to inspect webhook payloads:

  1. Go to webhook.site and copy the unique URL
  2. Create a webhook endpoint with this URL
  3. Trigger events in Broadcast to see the payloads

Local Development with ngrok

For local testing, use ngrok to create a secure tunnel:

# Start your local server
node server.js

# In another terminal, create a tunnel
ngrok http 3000

# Use the HTTPS URL from ngrok in your webhook endpoint

Best Practices

Handling Webhook Events

  1. Respond Quickly: Return a 200 status code within 30 seconds
  2. Process Asynchronously: Queue webhook events for background processing
  3. Handle Duplicates: Events may be sent multiple times; implement idempotency
  4. Validate Signatures: Always verify webhook signatures for security
  5. Log Events: Keep logs of webhook events for troubleshooting

Example Handler (Express.js)

app.post('/webhooks/broadcast', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['broadcast-webhook-signature'];
  const timestamp = req.headers['broadcast-webhook-timestamp'];
  const payload = req.body;

  // Verify signature first
  if (!verifyWebhook(payload, req.headers, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Parse the payload
  const event = JSON.parse(payload);

  // Queue for background processing
  queue.add('process-webhook', event);

  // Respond immediately
  res.status(200).send('OK');
});

Error Handling

If your webhook endpoint returns an error status code (4xx or 5xx), Broadcast will retry the delivery according to the retry schedule. To prevent retries for permanent failures, return a 200 status code but handle the error in your application logic.

Troubleshooting

Common Issues

Webhook not receiving events - Check that your endpoint URL is correct and accessible - Verify the endpoint is configured for the correct event types - Check firewall settings and SSL certificate validity

Signature verification failing - Ensure you’re using the correct webhook secret - Check that you’re calculating the signature correctly - Verify the timestamp is within the 5-minute window

High failure rates - Check your endpoint’s response time (must be under 30 seconds) - Verify your server can handle the webhook volume - Review error logs for specific failure reasons

Getting Help

If you’re experiencing issues with webhooks:

  1. Check the delivery logs in your webhook endpoint dashboard
  2. Review the error messages and response codes
  3. Test your endpoint with the built-in test webhook feature
  4. Contact support at [email protected] with your webhook endpoint details