The recipient marked the email as spam
Posted to the subscriptions to email.complained when the recipient marks the email as spam. The address joins the suppression list. Signed and retried like every event. The test event (POST /api/v1/webhooks/{id}/test) arrives under this type too, with data: { test: true, message } and none of the fields of the real event: check data.test first.
Headers
t=<unix timestamp>,v1=<hex>: v1 is the HMAC-SHA256 of "<t>.<raw body>" keyed with the subscription's secret. Reject a t more than 300 seconds away from your clock.
The same t, in seconds.
The event's id — the same on every attempt and every replay: the deduplication key.
The event's type.
This delivery. A manual replay gets a new one.
The attempt number, starting at 1.
Payload
Example payload
{
"id": "evt_Ab3cD9eF0gH1iJ2k",
"type": "email.bounced",
"created_at": "2026-09-25T08:31:09.020Z",
"data": {
"message_id": "cmu651xf200021n7nm68sikfw",
"email": "nobody@example.com",
"source": "api",
"subject": "Your September invoice",
"reason": "Permanent"
}
}Response
Any 2xx within 15 seconds acknowledges receipt. Anything else — another status, a redirect (not followed), no answer, a network error — is retried: 5 attempts in all, the next ones 30 s, 2 min, 10 min and 1 h after the previous failure.
Changes
Webhooks have no change history: a webhook is keyed by its event name rather than a path and method, so no recorded change can name it.