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 sentemail.delivered
- Email was delivered to the recipient’s inboxemail.delivery_delayed
- Email delivery was delayedemail.bounced
- Email bounced (hard or soft bounce)email.complained
- Recipient marked email as spamemail.opened
- Recipient opened the emailemail.clicked
- Recipient clicked a link in the emailemail.failed
- Email failed to send
Subscriber Events
subscriber.created
- New subscriber was addedsubscriber.updated
- Subscriber information was updatedsubscriber.deleted
- Subscriber was deletedsubscriber.subscribed
- Subscriber opted in or was reactivatedsubscriber.unsubscribed
- Subscriber opted outsubscriber.bounced
- Subscriber email bouncedsubscriber.complained
- Subscriber marked email as spam
System Events
message.attempt.exhausted
- All delivery attempts failedtest.webhook
- Test webhook event
Setting Up Webhooks
To set up a webhook endpoint:
- Go to Webhook Endpoints in your Broadcast dashboard sidebar
- Click Add Webhook Endpoint
- Enter your webhook URL (must be HTTPS)
- Select the event types you want to receive
- Optionally add a description
- 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 eventbroadcast-webhook-timestamp
- Unix timestamp when the webhook was sentbroadcast-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:
- Go to Webhook Endpoints
- Click on your webhook endpoint
- View delivery logs, success rates, and error messages
- 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:
- Go to webhook.site and copy the unique URL
- Create a webhook endpoint with this URL
- 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
- Respond Quickly: Return a 200 status code within 30 seconds
- Process Asynchronously: Queue webhook events for background processing
- Handle Duplicates: Events may be sent multiple times; implement idempotency
- Validate Signatures: Always verify webhook signatures for security
- 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:
- Check the delivery logs in your webhook endpoint dashboard
- Review the error messages and response codes
- Test your endpoint with the built-in test webhook feature
- Contact support at [email protected] with your webhook endpoint details