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
| Plan | Webhooks |
|---|---|
| Free | 0 |
| Pro | 3 |
| Scale | 10 |
Webhooks require a Pro or Scale plan. Upgrade at notify.cx/pricing.
Supported event types
| Event Type | Description |
|---|---|
Send | Email accepted by Notify |
Delivery | Delivered to recipient's mail server |
Open | Recipient opened the email |
Click | Recipient clicked a link |
Bounce | Rejected by recipient's mail server |
Complaint | Marked as spam |
DeliveryDelay | Delivery temporarily delayed |
Set up via dashboard
- Go to Webhooks
- Click Add Webhook
- Select the verified domain this webhook should cover
- Choose whether to match the entire domain, specific subdomain(s), or specific from address(es)
- Enter your endpoint URL
- Select events to subscribe to
- 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:
matchMode | Extra fields | Fires when the from-host / from-address is |
|---|---|---|
domain (default) | none | the verified domain or any subdomain |
hosts | matchHosts (1–20 hostnames) | a listed host or a child of a listed host |
froms | matchFroms (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
- Return
200within 10 seconds — process events asynchronously - Handle duplicate deliveries idempotently
- Monitor your endpoint for failures
- Use the
message_idto correlate with email logs - Keep webhook URLs private — there is no request signature today