Skip to content
Bring your own SMTP or SES — pay AWS rates, not SaaS rates

Webhooks

20 events,
signed and retried.

MailerSpark pushes events to your endpoints with HMAC-SHA256 signatures. Failed deliveries are retried with exponential backoff. Endpoint URLs are SSRF-scanned before they're saved.

How it works

You register a webhook endpoint in Settings → Integrations → Webhooks. We POST a JSON payload to your URL whenever a matching event happens. The request is signed with your endpoint's secret using HMAC-SHA256. You verify the signature, process the event, and return 2xx. If we don't get a 2xx, we retry with exponential backoff.

POST your-endpoint.com/webhooks
{
  "id": "evt_2n4k9",
  "type": "email.opened",
  "createdAt": "2026-04-15T10:23:11Z",
  "data": {
    "campaignId": "cmp_8a3f",
    "contactId": "ct_5h2k",
    "email": "alex@acme.com",
    "userAgent": "Mozilla/5.0...",
    "ip": "203.0.113.42"
  }
}

Verifying the signature

Every webhook request includes three headers. Compute the HMAC of the raw request body using your endpoint's secret and compare.

X-MailerSpark-Signature: t=1700000000,v1=4f3a...
X-MailerSpark-Event: email.opened
X-MailerSpark-Delivery: dlv_8x2k
# Node.js example
const crypto = require('crypto');

function verify(req, secret) {
  const sig = req.headers['x-mailerspark-signature'];
  const [tsPart, sigPart] = sig.split(',');
  const ts = tsPart.split('=')[1];
  const expected = sigPart.split('=')[1];
  const payload = ts + '.' + req.rawBody;
  const computed = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(computed, 'hex')
  );
}

Event types

Subscribe to one or many. The list below is current; new events ship regularly and will appear in your dashboard changelog.

EventWhen it fires
email.sentAn email was accepted by the transport (SMTP/SES)
email.deliveredThe transport confirmed delivery
email.openedThe recipient's client loaded the tracking pixel
email.clickedThe recipient clicked a tracked link
email.bouncedThe transport reported a hard or soft bounce
email.complainedThe recipient marked the message as spam
email.unsubscribedThe recipient clicked the unsubscribe link
email.repliedA cold outreach recipient replied (lands in Unibox)
lead.status_changedA lead transitioned between pipeline statuses
campaign.scheduledA campaign was scheduled for sending
campaign.startedA campaign began sending
campaign.completedA campaign finished sending to all recipients
campaign.pausedA campaign was paused
campaign.failedA campaign entered a failed state
contact.createdA new contact was created
contact.subscribedA contact subscribed (newsletter or after opt-in)
contact.unsubscribedA contact unsubscribed
sequence.step_sentA cold outreach sequence step was sent
sequence.completedA sequence finished for a recipient
inbox.health_warningAn inbox token expired or warmup is behind

Retries

If your endpoint returns a non-2xx response, or doesn't respond within 10 seconds, we retry. The schedule is exponential backoff: 30s, 2m, 10m, 1h, 6h, 24h. After the final attempt, the delivery is marked as failed and visible in the Webhooks delivery log.

SSRF protection

When you save a webhook endpoint URL, we SSRF-scan it: no private IPs, no link-local, no localhost, no metadata endpoints. The check happens on save and on retry. If your endpoint moves, you'll get a clear error.

Growth and above

Webhooks on Growth and above.

Pair with the REST API for full read/write access to MailerSpark from your own services.

Encrypted in transitGDPR readyNo credit card