---
title: email.bounced
description: Delivery failed. Creates a suppression automatically.
sidebar:
  label: email.bounced
  icon: circle-x
---

Delivery failed. Creates a [suppression](/guides/suppressions) automatically, so the next send to that address never leaves.

## Payload

| Prop | Type | Default | Description |
| - | - | - | - |
| `email_id` | `string` | - | eml_… |
| `thread_id` | `string` | - | The conversation. |
| `domain_id` | `string \| null` | - | The domain it was sent from, or null when sent through a mailbox. |
| `mailbox_id` | `string \| null` | - | The mailbox it was sent through, or null when sent from a domain. |
| `suppression_key` | `string \| null` | - | The list the send named, when it named one. |
| `recipients` | `string[]` | - | Which recipients bounced. |
| `permanent` | `boolean` | - | true for a hard bounce — the address doesn't exist. false for a soft one — full mailbox, temporary failure. |
| `reason` | `string` | - | What the receiving server said. |

## Handling it

```ts
if (event.type === "email.bounced" && event.data.permanent) {
  await markUndeliverable(event.data.recipients, event.data.reason)
}
```

A permanent bounce means the address is wrong — stop showing it as valid in your own UI. A soft bounce is usually transient and not worth acting on.

The suppression a hard bounce writes goes on the workspace's `*` list whatever `space_id` the event carries — the address exists for nobody, so no [space](/guides/spaces) should try it either.
