> AI agents: this is one page from PostHog's docs. Full index of Markdown docs for LLMs: https://posthog.com/llms.txt # Opt-outs and suppression Before a workflow sends anything, PostHog checks two lists: the recipient's **opt-out preferences** and the project's **suppression list**. Both live under **Workflows** in [PostHog](https://app.posthog.com), and neither is something a workflow can override. The difference matters. An opt-out is a choice the recipient made – they don't want this kind of message. A suppression is a delivery fact – mail to this address bounced, or you added it by hand, so PostHog stops trying. ## Message categories Opt-outs are organized into **message categories**, so someone can decline your product newsletter and still get a password reset. Each category has a name, an internal description, a public description shown to recipients on the preferences page, and a type – **marketing** or **transactional**. Create the categories you actually send against, then pick one on each message step in the [workflow builder](/docs/workflows/workflow-builder.md). Recipients who have opted out of that category are skipped. ## The opt-out list The opt-out list shows who has opted out of which category. Recipients land on it in a few ways: a one-click unsubscribe from an email client, the preferences page behind `{{unsubscribe_url}}` in your [email templates](/docs/workflows/library.md#email-merge-tags), an import from another tool, or you adding them directly. Every genuine transition from opted-in to opted-out also writes a `$workflows_email_unsubscribed` event, carrying the `category` and the `source` (`one_click` or `preferences_page`). See [workflow events](/docs/workflows/engagement-events.md#properties-on-unsubscribe-events) for the full property list, and note that repeated unsubscribe requests do not emit duplicate events. Coming from Customer.io? [Import your opt-out lists](/docs/workflows/import-customerio-optouts.md) and keep them in sync with a reporting webhook. ## The suppression list The suppression list is address-level and category-independent – a suppressed recipient receives nothing. Each entry records the recipient, how it got there (**bounces** or **manual**), the reason or last bounce diagnostic, and when it was suppressed. PostHog adds addresses automatically when mail to them hard-bounces, which is what protects your sending domain's reputation. You can add an address by hand, and you can remove an entry if you believe the bounce was a one-off – but removing a genuine hard bounce means you'll bounce again. ## Managing the lists over the API Both lists are available over the [REST API](/docs/api.md), so your own product can honor an unsubscribe or a resubscribe without anyone opening PostHog. The [messaging preferences API](/docs/api/messaging-preferences.md) manages the opt-out list: list a category's opt-outs, add them one at a time or up to 1,000 in bulk, remove one when a recipient opts back in, and export a category's list as CSV. Leave out the category to work with the global opt-out that covers all marketing messages. Sends check the message's category and the global opt-out together, so opting someone back in to one marketing category also lifts a global opt-out if they have one. Their other marketing categories stay opted out, which keeps the resubscribe scoped to the category you named. The [messaging suppressions API](/docs/api/messaging-suppressions.md) manages the suppression list: list entries, add one, or remove one. Authenticate with a [personal API key](/docs/api/personal-api-keys.md) that has the `hog_flow:read` scope for reads or `hog_flow:write` for writes. ## Related - [Import opt-out lists from Customer.io](/docs/workflows/import-customerio-optouts.md) - [Content library and message templates](/docs/workflows/library.md) – adding unsubscribe links to emails - [Workflow events](/docs/workflows/engagement-events.md) – unsubscribe and bounce events in your project ### Still have questions? Ask PostHog AI ### Was this page useful? HelpfulCould be better