Skip to content

Webhooks

Notavia POSTs webhooks to your configured endpoint whenever something happens to a message you sent — or to a provider you send through. Each request is signed (Svix-style HMAC-SHA256) so you can prove it came from Notavia. Always verify before acting on a payload.

Subscribe to specific events when you create an endpoint, or leave the filter empty to receive all of them.

| Event | When it fires | | --- | --- | | notification.sent | Accepted by the provider. | | notification.delivered | The provider confirmed delivery to the mailbox. | | notification.bounced | Hard or soft bounce. The recipient is auto-suppressed on a hard bounce. | | notification.complained | The recipient marked it as spam. Auto-suppressed. | | notification.failed | Every provider in the chain failed. The message is not going out. | | provider.critical | One of your email providers is failing your sends right now. | | provider.recovered | That provider is delivering again. |

provider.critical and provider.recovered require a Pro plan or above. They are the machine-readable half of provider alerting — wire them to your pager and you will know your provider is down before your users tell you.

{
"provider": "Resend",
"environment": "Live",
"messages": 42,
"failed_messages": 42,
"failure_rate": 100,
"firing_since": "2026-07-14T05:41:34.370618+00:00"
}

messages and failed_messages count distinct messages, not delivery attempts — a single message the provider retried three times is one failed message, not three. failure_rate is a percentage.

The event id is stable for the life of one outage: if we have to retry the delivery of this webhook, you receive the same id, so you can dedupe on it rather than paging twice for the same incident. A new outage on the same provider gets a new id.

{
"provider": "Resend",
"environment": "Live",
"recovered_at": "2026-07-14T06:05:12.118433+00:00"
}

We only send this when the provider has actually delivered mail again — not merely because it went quiet. A dead provider stops producing traffic, and treating that silence as recovery would tell you it was fixed in the middle of an outage.

Every SDK ships a byte-faithful verification helper — use it rather than rolling your own:

bool ok = WebhookSignatures.Verify(secret, headers, rawBody);

Pass the raw request body (not the parsed JSON) and the request headers. Find your signing secret in Settings → Webhooks.