Mailcub logo
Back to Documentation

Webhooks

Receive real-time notifications about email events through HTTP callbacks to your application.

What are Webhooks?

Webhooks are HTTP callbacks that MailCub sends to your application when specific events occur. Instead of constantly polling our API for updates, webhooks allow you to receive real-time notifications about email delivery status, opens, clicks, and more.

Benefits:

  • • Real-time event notifications
  • • Reduced API calls and costs
  • • Better user experience
  • • Automatic retry mechanism

Use Cases:

  • • Update delivery status in your database
  • • Trigger follow-up actions
  • • Track email engagement
  • • Handle bounces and complaints

Setting Up Webhooks

1

Create a Webhook Endpoint

Create an HTTP endpoint in your application that can receive POST requests from MailCub.

// Express.js example
app.post('/webhooks/mailcub', (req, res) => {
  const event = req.body;
  
  // Process the webhook event
  console.log('Received event:', event.type);
  
  // Respond with 200 to acknowledge receipt
  res.status(200).send('OK');
});
2

Configure in Dashboard

Add your webhook URL in the MailCub dashboard under Settings → Webhooks.

  • Enter your webhook URL (must be HTTPS in production)
  • Select which events you want to receive
  • Test the webhook with a sample event
3

Verify and Handle Events

Implement signature verification and event handling logic in your application.

Event Types

email.sent payload
{
  "id": "evt_1234567890",
  "type": "email.sent",
  "data": {
    "email_id": "msg_abcdef123456",
    "to": "user@example.com",
    "subject": "Welcome!",
    "sent_at": "2025-01-15T10:30:00Z"
  }
}

Security & Verification

Webhook Signature Verification

Always verify webhook signatures to ensure requests are actually from MailCub and haven't been tampered with.

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');
    
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

// Usage in your webhook handler
app.post('/webhooks/mailcub', (req, res) => {
  const signature = req.headers['x-mailcub-signature'];
  const payload = JSON.stringify(req.body);
  
  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Unauthorized');
  }
  
  // Process the verified webhook
  handleWebhookEvent(req.body);
  res.status(200).send('OK');
});

Best Practices

✅ Do

  • • Always verify webhook signatures
  • • Respond with HTTP 200 for successful processing
  • • Process webhooks idempotently
  • • Use HTTPS endpoints in production
  • • Implement proper error handling
  • • Log webhook events for debugging
  • • Handle duplicate events gracefully

❌ Don't

  • • Take longer than 10 seconds to respond
  • • Process webhooks without verification
  • • Expose sensitive data in webhook URLs
  • • Ignore failed webhook deliveries
  • • Use HTTP (non-HTTPS) endpoints
  • • Assume webhooks arrive in order
  • • Process the same event multiple times

Error Handling & Retries

Retry Policy

If your webhook endpoint doesn't respond with a 2xx status code, MailCub will retry the delivery:

  • 1st retry: After 1 minute
  • 2nd retry: After 5 minutes
  • 3rd retry: After 30 minutes
  • 4th retry: After 2 hours
  • 5th retry: After 6 hours

Webhook Disabled

If all retries fail, the webhook will be automatically disabled. You can re-enable it in your dashboard after fixing the issue.

Testing Webhooks

Local Development

For local testing, you can use tools like ngrok to expose your local server to the internet:

# Install ngrok
npm install -g ngrok

# Expose your local server
ngrok http 3000

# Use the HTTPS URL in your webhook configuration
# Example: https://abc123.ngrok.io/webhooks/mailcub

Test Events

You can send test webhook events from your MailCub dashboard to verify your endpoint is working correctly.

Dashboard → Settings → Webhooks → Test Webhook