Webhooks & Notifications

Receive real-time email event notifications via webhooks.

Webhooks push email events to your server as they happen — delivery, opens, clicks, bounces, and more. Use them to update your database, trigger workflows, or alert on failures without polling the logs API.

Every webhook is scoped to one verified sending domain. That domain authorizes events; you can optionally narrow delivery to listed subdomains or from addresses without verifying extra domains. If you omit the extra filter, events fire for the verified domain and all of its subdomains (same coverage rule as sending). If you run multiple sites, create separate webhooks per domain — for example, one Discord channel for shop.com and another for blog.com.

Webhook limits by plan

PlanWebhooks
Free0
Pro3
Scale10

Webhooks require a Pro or Scale plan. Upgrade at notify.cx/pricing.

Supported event types

Event TypeDescription
SendEmail accepted by Notify
DeliveryDelivered to recipient's mail server
OpenRecipient opened the email
ClickRecipient clicked a link
BounceRejected by recipient's mail server
ComplaintMarked as spam
DeliveryDelayDelivery temporarily delayed

Set up via dashboard

  1. Go to Webhooks
  2. Click Add Webhook
  3. Select the verified domain this webhook should cover
  4. Choose whether to match the entire domain, specific subdomain(s), or specific from address(es)
  5. Enter your endpoint URL
  6. Select events to subscribe to
  7. Click Create Webhook

Set up via API

curl -X POST https://notify.cx/api/webhooks \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "webhookUrl": "https://example.com/webhook",
    "subscribedEvents": ["Delivery", "Bounce", "Open"],
    "domainId": "123e4567-e89b-12d3-a456-426614174000",
    "matchMode": "hosts",
    "matchHosts": ["outreach.example.com"]
  }'

Response:

{
  "success": true,
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "webhookUrl": "https://example.com/webhook",
    "subscribedEvents": ["Delivery", "Bounce", "Open"],
    "domainId": "123e4567-e89b-12d3-a456-426614174000",
    "domain": "example.com",
    "matchMode": "hosts",
    "matchHosts": ["outreach.example.com"],
    "matchFroms": [],
    "createdAt": "2025-04-10T12:00:00Z"
  }
}

Manage webhooks

List all webhooks:

curl -X GET https://notify.cx/api/webhooks \
  -H "x-api-key: your_api_key"

Update subscribed events:

curl -X PUT https://notify.cx/api/webhooks/123e4567-e89b-12d3-a456-426614174000 \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "subscribedEvents": ["Delivery", "Bounce"]
  }'

Delete a webhook:

curl -X DELETE https://notify.cx/api/webhooks/123e4567-e89b-12d3-a456-426614174000 \
  -H "x-api-key: your_api_key"

Test a webhook

Send a test payload without sending a real email:

curl -X POST https://notify.cx/api/webhooks/test \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "webhookUrl": "https://example.com/webhook",
    "eventType": "Delivery"
  }'

Payload format

Your endpoint receives a POST with JSON like:

{
  "timestamp": "2025-04-10T15:30:45Z",
  "event_type": "Delivery",
  "message_id": "0102018494848484-b51e7343-6808-4a68-b2af-845feae57f8b-000000",
  "source": "noreply@mail.example.com",
  "domain": "example.com",
  "destination": "recipient@example.com",
  "raw_event_data": {
    "deliveryTimestamp": "2025-04-10T15:30:45Z",
    "deliveredRecipients": ["recipient@example.com"],
    "processingTimeMillis": 257
  }
}

Fields in raw_event_data vary by event type. source is the email's from address; domain is the verified domain this webhook was scoped to (the parent you selected, even if you filtered to a subdomain).

Match filters

domainId is always the verified parent. Use matchMode so one verified domain can feed several apps:

matchModeExtra fieldsFires when the from-host / from-address is
domain (default)nonethe verified domain or any subdomain
hostsmatchHosts (1–20 hostnames)a listed host or a child of a listed host
fromsmatchFroms (1–20 emails)an exact listed from address (case-insensitive)

Hosts and from addresses must be covered by the verified domain. You do not need to verify outreach.example.com separately to match it.

Example — only mail from hello@outreach.example.com:

curl -X POST https://notify.cx/api/webhooks \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "webhookUrl": "https://example.com/webhook",
    "subscribedEvents": ["Delivery", "Bounce"],
    "domainId": "123e4567-e89b-12d3-a456-426614174000",
    "matchMode": "froms",
    "matchFroms": ["hello@outreach.example.com"]
  }'

Signature verification

Notify webhook deliveries today are not signed with an HMAC secret header. Treat endpoint URLs as secrets (use long random paths), require HTTPS, and verify events by correlating message_id with the email logs API when you need stronger assurance.

If signed webhooks land on the roadmap, this section will be updated with verification examples.

Best practices

  1. Return 200 within 10 seconds — process events asynchronously
  2. Handle duplicate deliveries idempotently
  3. Monitor your endpoint for failures
  4. Use the message_id to correlate with email logs
  5. Keep webhook URLs private — there is no request signature today

Next steps