Webhooks

Receive real-time notifications when events occur in your MimeProtect account.

What are Webhooks?

Webhooks allow your application to receive real-time HTTP notifications when events occur in your MimeProtect account. Instead of polling the API for updates, MimeProtect will automatically send POST requests to your configured endpoint whenever relevant events happen.

Common use cases for webhooks include:

  • Triggering alerts in your monitoring systems when security issues are detected
  • Syncing DMARC report data to your internal dashboards
  • Automating workflows when domain verification completes
  • Integrating with ticketing systems for alert management

Webhook Events

MimeProtect can send webhooks for the following event types. You can configure which events you want to receive when setting up your webhook endpoint.

alert.created
alert

Triggered when a new security alert is generated

alert.resolved
alert

Triggered when an existing alert is marked as resolved

domain.scan_completed
domain

Triggered when a domain scan finishes processing

domain.verified
domain

Triggered when domain ownership verification succeeds

report.received
report

Triggered when a new DMARC or TLS-RPT report is received

Payload Format

All webhook payloads follow a consistent structure with the event type, timestamp, and event-specific data. Below are examples for each event type.

alert.created
Sent when a new security alert is triggered for your domain.
{
  "id": "evt_1a2b3c4d5e6f",
  "type": "alert.created",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "alert": {
      "id": "alt_abc123",
      "type": "dmarc_failure_spike",
      "severity": "high",
      "domain_id": "dom_xyz789",
      "domain_name": "example.com",
      "title": "DMARC Failure Spike Detected",
      "description": "DMARC failure rate increased from 2% to 15% in the last 24 hours",
      "created_at": "2024-01-15T10:30:00Z",
      "metadata": {
        "failure_rate": 15.2,
        "previous_rate": 2.1,
        "affected_sources": ["192.168.1.100", "10.0.0.50"]
      }
    }
  }
}

Signature Verification

HMAC-SHA256 Signatures
Verify webhook authenticity to ensure requests are from MimeProtect.

Every webhook request includes an X-MimeProtect-Signature header containing a timestamp and HMAC-SHA256 signature. You should always verify this signature to ensure the webhook was sent by MimeProtect and has not been tampered with.

Verification Steps

  1. Extract the timestamp and signature from the header
  2. Verify the timestamp is within 5 minutes of current time (prevents replay attacks)
  3. Concatenate the timestamp and JSON payload with a period: {timestamp}.{payload}
  4. Compute HMAC-SHA256 using your webhook secret
  5. Compare the computed signature with the received signature using timing-safe comparison

Code Examples

Below are complete examples showing how to verify webhook signatures and handle events in popular programming languages.

Node.js / Express
Using the built-in crypto module for signature verification.
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const timestamp = signature.split(',')[0].split('=')[1];
  const receivedSignature = signature.split(',')[1].split('=')[1];

  // Verify timestamp is within 5 minutes to prevent replay attacks
  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
    throw new Error('Webhook timestamp is too old');
  }

  // Create the signed payload
  const signedPayload = `${timestamp}.${payload}`;

  // Calculate the expected signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  // Use timing-safe comparison
  const isValid = crypto.timingSafeEqual(
    Buffer.from(receivedSignature),
    Buffer.from(expectedSignature)
  );

  if (!isValid) {
    throw new Error('Invalid webhook signature');
  }

  return true;
}

// Express.js example
app.post('/webhooks/mimeprotect', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-mimeprotect-signature'];
  const payload = req.body.toString();

  try {
    verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET);

    const event = JSON.parse(payload);

    // Handle the webhook event
    switch (event.type) {
      case 'alert.created':
        handleNewAlert(event.data.alert);
        break;
      case 'report.received':
        handleNewReport(event.data.report);
        break;
      // ... handle other events
    }

    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook error:', error.message);
    res.status(400).send('Invalid signature');
  }
});

Setting Up Webhooks

Configure Your Webhook Endpoint
Set up webhooks in your MimeProtect integrations settings.
  1. Navigate to /app/integrations in your MimeProtect dashboard
  2. Click "Add Webhook" to create a new webhook endpoint
  3. Enter your webhook URL (must be HTTPS in production)
  4. Select which events you want to receive
  5. Copy the generated webhook secret for signature verification
  6. Test your endpoint using the "Send Test Event" button

Retry Policy

Automatic Retries
MimeProtect automatically retries failed webhook deliveries.

If your endpoint returns an error or times out, MimeProtect will retry the webhook delivery using exponential backoff:

AttemptDelayApproximate Time
1st retry1 minute~1 min after initial failure
2nd retry5 minutes~6 min after initial failure
3rd retry (final)30 minutes~36 min after initial failure

Response Requirements

Endpoint Requirements
Your webhook endpoint must meet these requirements for successful delivery.

Response Status

Return any 2xx status code (200-299) to acknowledge receipt. Any other status code will trigger a retry.

Response Time

Your endpoint must respond within 30 seconds. Requests that take longer will time out and trigger a retry.

HTTPS Required

Webhook endpoints must use HTTPS in production. HTTP endpoints are only allowed for local development testing.

Idempotency

Your endpoint should handle duplicate events gracefully. Use the event id field to deduplicate.