Webhook Integration Guide
Learn how to integrate webhooks into your application to receive real-time notifications about email events and other actions.
Overview
Webhooks allow your application to receive real-time notifications when events occur in Metigan. Instead of polling for updates, webhooks push data to your server as soon as events happen.
1. Create Webhook
Set up a webhook endpoint in your Metigan dashboard or via API
2. Receive Events
Your endpoint receives POST requests with event data
3. Verify & Process
Verify the signature and process the event in your app
Quick Start
Here's a minimal example to get started with webhooks in Node.js:
import express from 'express';
import crypto from 'crypto';
const app = express();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET!;
// IMPORTANT: Use express.raw() to preserve the raw body for signature verification
app.post('/webhooks/metigan', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'] as string;
const payload = req.body.toString();
// Verify the signature
if (!verifySignature(payload, signature, WEBHOOK_SECRET)) {
console.error('Invalid webhook signature');
return res.status(401).send('Invalid signature');
}
// Parse and process the event
const event = JSON.parse(payload);
switch (event.event) {
case 'email.delivered':
console.log(`Email delivered to ${event.data.recipient}`);
break;
case 'email.opened':
console.log(`Email opened by ${event.data.recipient}`);
break;
case 'email.clicked':
console.log(`Link clicked in email to ${event.data.recipient}`);
break;
case 'email.bounced':
console.log(`Email bounced for ${event.data.recipient}`);
break;
default:
console.log(`Received event: ${event.event}`);
}
res.status(200).send('OK');
});
function verifySignature(payload: string, signature: string, secret: string): boolean {
try {
const parts = signature.split(',');
const timestamp = parseInt(parts.find(p => p.startsWith('t='))!.slice(2));
const providedSig = parts.find(p => p.startsWith('v1='))!.slice(3);
// Check timestamp (5 minute tolerance)
if (Math.floor(Date.now() / 1000) - timestamp > 300) return false;
// Verify HMAC
const expectedSig = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${payload}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(providedSig), Buffer.from(expectedSig));
} catch {
return false;
}
}
app.listen(3000, () => console.log('Webhook server running on port 3000'));The signature uses HMAC-SHA256 with the format t=timestamp,v1=signature. The signed payload is timestamp.payload (timestamp dot raw JSON body).
Common Use Cases
📊 Track Email Engagement
Use email.opened and email.clicked events to track user engagement and update your analytics.
// Update user engagement score when they interact with emails
switch (event.event) {
case 'email.opened':
await db.users.updateEngagement(event.data.userId, { opens: 1 });
break;
case 'email.clicked':
await db.users.updateEngagement(event.data.userId, { clicks: 1 });
break;
}🚫 Handle Bounces
Automatically clean your mailing list when emails bounce.
if (event.event === 'email.bounced') {
const { recipient, bounceType } = event.data;
if (bounceType === 'hard') {
// Permanently invalid address - remove from list
await db.contacts.markInvalid(recipient);
} else {
// Soft bounce - retry later
await db.contacts.incrementBounceCount(recipient);
}
}⚠️ Monitor Spam Complaints
Handle spam complaints to maintain sender reputation.
if (event.event === 'email.complained') {
const { recipient } = event.data;
// Unsubscribe user immediately
await db.contacts.unsubscribe(recipient, 'spam_complaint');
// Alert your team
await slack.notify(`⚠️ Spam complaint from ${recipient}`);
}Best Practices
Always verify signatures
Never process webhook data without verifying the HMAC signature first.
Respond quickly
Return a 2xx response within 30 seconds. For long operations, queue the work and respond immediately.
Use HTTPS only
Webhook endpoints must use HTTPS to ensure data is encrypted in transit.
Handle idempotency
Use the messageId to ensure you don't process the same event twice if retries occur.
Always verify webhook signatures to ensure requests are authentic. Never process webhook payloads without verification. See the Webhooks API documentation for complete code examples.
Testing Webhooks
You can test your webhook integration directly from the Metigan dashboard:
- Go to Settings → Webhooks in your dashboard
- Select the webhook you want to test
- Click the "Test Webhook" button
- Choose an event type and send a test payload
- Check the delivery history to see the result
For local development, you can use tools like ngrok or localtunnel to expose your local server to the internet.