Using Webhooks

Webhooks notify your application in real time when events happen — a contact subscribes, an email is opened, a campaign is sent.

Create a webhook

curl -X POST https://api.cakemail.dev/webhooks \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/cakemail",
    "events": ["Contact.Added", "Email.Opened", "Campaign.Sent"],
    "rate_limit": 100,
    "rate_limit_period": "hour"
  }'

The response includes a webhook_id and a secret for signature verification.

Available events

EventTriggered when
Contact.AddedA contact is added to a list
Contact.UnsubscribedA contact unsubscribes
Email.OpenedA recipient opens an email
Email.ClickedA recipient clicks a link
Email.BouncedAn email bounces
Campaign.SentA campaign finishes sending
Campaign.ScheduledA campaign is scheduled

See the API reference for the full list.

Retrieve webhook details

Fetch a webhook's configuration, including its secret and hash_function, using its ID:

curl "https://api.cakemail.dev/webhooks/{webhook_id}" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

The response contains the webhook's URL, subscribed events, rate limit settings, secret key, and hash function used for signature verification.

Verify webhook signatures

Each webhook request includes a signature header. Verify it to ensure the request is authentic:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('base64');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Webhook payload structure

When an event fires, Cakemail sends a POST request to your endpoint. The request includes a signature header and a JSON body:

Header:

X-Cakemail-Signature: BASE64_ENCODED_HMAC_SIGNATURE

Body:

{
  "event": "Email.Opened",
  "timestamp": "2026-04-10T14:32:00Z",
  "data": {
    "email_id": "e_abc123",
    "contact_id": "c_def456",
    "campaign_id": "cmp_ghi789",
    "list_id": "lst_jkl012",
    "email_address": "recipient@example.com",
    "opened_at": "2026-04-10T14:32:00Z"
  }
}

The exact fields inside data vary by event type. Refer to the API reference for the schema of each event.

List your webhooks

curl "https://api.cakemail.dev/webhooks" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Archive a webhook

Webhooks can't be deleted, but they can be archived (disabled):

curl -X POST https://api.cakemail.dev/webhooks/{webhook_id}/archive \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

To re-enable, use the unarchive endpoint.

Limitations

Only Next-gen API events are supported. Legacy API events are not forwarded to webhooks.