// reference

Webhooks.

We POST every delivery state change to a URL you control. Events are signed with HMAC-SHA256 and delivered with at-least-once semantics — dedupe by event id.

Verifying signatures

Each request carries a VoltMail-Signature header containing an HMAC-SHA256 of the raw request body, keyed with your endpoint secret.

ts// Node — verify the signature header
import crypto from 'crypto';

function verify(body: string, header: string, secret: string) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(header),
    Buffer.from(expected),
  );
}

Events

email.sent

Message accepted by the receiving SMTP server.

Fires once per recipient, after the receiver has acknowledged with a 2xx SMTP response.

payload{
  "id": "evt_01HV9X8T2U3V4W5X6Y7Z8A9B0C",
  "type": "email.sent",
  "created_at": "2026-05-01T12:00:01Z",
  "data": {
    "email_id": "em_01HV9X3Q8K2BM0F7Z8E5T6Y9N3",
    "to": "jane@example.com",
    "subject": "Your receipt"
  }
}
email.delivered

Receiver confirmed delivery to the recipient mailbox.

Fires when the destination MTA returns a 250 OK after queue processing — usually within seconds of email.sent.

payload{
  "id": "evt_01HV9X8U3V4W5X6Y7Z8A9B0C1D",
  "type": "email.delivered",
  "created_at": "2026-05-01T12:00:08Z",
  "data": {
    "email_id": "em_01HV9X3Q8K2BM0F7Z8E5T6Y9N3",
    "to": "jane@example.com",
    "smtp_response": "250 2.0.0 OK"
  }
}
email.bounced

Hard or soft bounce.

Fires when the receiver returns a 4xx (soft) or 5xx (hard) SMTP response. Hard bounces auto-suppress the address.

payload{
  "type": "email.bounced",
  "data": {
    "email_id": "em_01HV9X3Q…",
    "to": "missing@example.com",
    "bounce_type": "hard",
    "diagnostic": "550 5.1.1 user unknown"
  }
}
email.complained

Recipient marked the email as spam.

Fires when an FBL (feedback loop) provider reports a complaint. The address is auto-suppressed.

payload{
  "type": "email.complained",
  "data": {
    "email_id": "em_01HV9X3Q…",
    "to": "angry@example.com",
    "feedback_type": "abuse"
  }
}
email.opened

Tracking pixel fetched.

Fires the first time the tracking pixel is loaded for this email. Subsequent opens are deduplicated within 24 hours.

payload{
  "type": "email.opened",
  "data": {
    "email_id": "em_01HV9X3Q…",
    "to": "jane@example.com",
    "user_agent": "Mozilla/5.0 (iPhone; …) Mobile",
    "ip": "203.0.113.42"
  }
}
email.clicked

Recipient clicked a tracked link.

Fires once per (email_id, url) pair on the first click. Repeat clicks are recorded in analytics but not redelivered.

payload{
  "type": "email.clicked",
  "data": {
    "email_id": "em_01HV9X3Q…",
    "to": "jane@example.com",
    "url": "https://acme.dev/orders/4711"
  }
}
email.unsubscribed

Recipient hit one-click unsubscribe.

Fires when a recipient uses the List-Unsubscribe-Post header. Address is auto-suppressed across the workspace.

payload{
  "type": "email.unsubscribed",
  "data": {
    "email_id": "em_01HV9X3Q…",
    "to": "jane@example.com",
    "method": "list-unsubscribe-post"
  }
}