---
title: "Email bounced"
method: POST
path: "email.bounced"
tags: ["Webhook Events"]
---

# Email bounced

`POST email.bounced` (webhook)

A delivery failure report for mail the mailbox sent arrived: the receiving server refused it for a recipient. Fires for every send from the mailbox, once per failed recipient. Delayed-delivery warnings and out-of-office replies do not fire it.

Act on `recommendedAction`: `remove` means the address does not take mail. Refusals on the sending side (`auth_failure`, `blocklisted`, `spam_blocked`, `policy_blocked`) never say `remove`. The report also arrives as `message.received`, and it does not count as a reply for `email.thread_replied`.

## Payload

- WebhookPayloadEmailBounced: Webhook payload for email.bounced. One event per failed recipient of the bounce.
  - `id` string, required
  - `profiles` object[]: The profiles this event belongs to, each with the externalId you set on it (null when none is set). Use it to route the event to your tenant without storing Zernio profile ids. Present on every event tied to a profile, absent on events that belong to none. Events spanning several profiles (a post published to accounts of different profiles) list each once.
    - `id` string, required
    - `externalId` string, nullable, required
  - `test` boolean: Always true when present: only a sample sent by POST /v1/webhooks/test with an event carries it. Real deliveries never do.
  - `event` 'email.bounced', required
  - `account` object, required
    - `accountId` string
    - `profileId` string
    - `platform` string
    - `username` string
    - `displayName` string, nullable
  - `email` object, required: The mail that bounced. `messageId`, `trackingId` and `metadata` are set when it was sent with tracking; otherwise match on `threadId`, `internetMessageId` or `subject`.
    - `messageId` string, nullable: Provider id of the sent mail.
    - `threadId` string
    - `internetMessageId` string, nullable: The RFC 5322 Message-ID of the mail that bounced.
    - `trackingId` string, nullable
    - `metadata` object, nullable
    - `subject` string, nullable: From the headers the report quotes.
    - `sentAt` string, date-time, nullable: From the headers the report quotes.
  - `bounce` object, required
    - `recipient` string: The address that refused the mail.
    - `type` 'hard' | 'soft' | 'undetermined': `hard`: 5.x.x, the address does not take mail. `soft`: 4.x.x, a temporary refusal the sending server gave up on. `undetermined`: the report gave no status.
    - `category` 'user_unknown' | 'mailbox_full' | 'domain_not_found' | 'policy_blocked' | 'spam_blocked' | 'blocklisted' | 'message_too_large' | 'content_rejected' | 'auth_failure' | 'rate_limited' | 'other'
    - `status` string, nullable: RFC 3463 enhanced status, such as 5.1.1.
    - `smtpCode` integer, nullable: The SMTP reply code, such as 550. Always a number.
    - `diagnostic` string, nullable: The receiving server's answer.
    - `recommendedAction` 'remove' | 'retry' | 'review' | 'fix_configuration': `remove` only for an address that does not take mail. Sender-side refusals (authentication, blocklists, spam filters) are `fix_configuration` or `review`, never `remove`.
    - `reportingMta` string, nullable
    - `detection` 'dsn' | 'ndr': `dsn`: a standard delivery report with the bounced Message-ID. `ndr`: a non-standard report read from its headers and text.
    - `bounceMessageId` string: Provider id of the bounce report in the mailbox.
    - `bouncedAt` string, date-time: When the report arrived in the mailbox.
    - `detectedAt` string, date-time: When Zernio read it. Reports can arrive minutes to days after the send.
  - `timestamp` string, date-time, required

## Acknowledgement `200`

Webhook received successfully

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) - [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/a79c233ebf22?raw)
