> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Message suppression model: the duplicate-content guard, and the two mechanisms it is not

> Message suppression is a content-hash duplicate guard that skips identical bodies before the frequency cap — distinct from consent suppression (the opt-out gate) and the suppression list (the imported block list). This page tells the three apart.

# Message suppression model

**Message suppression** is the content-hash duplicate guard: a send is silently skipped when the identical body already reached the same contact on the same channel inside a window you choose. It is a safety net against double-sends — not a compliance control, and not the contact block list.

Three mechanisms in Orbit all answer to "suppression" and are routinely confused for one another. This page tells them apart: which question each answers, where each sits in the send pipeline, which console and API each lives behind, and which one to reach for.

## One-line semantic

> **Suppression list is compliance-owned; message suppression is a safety net; consent suppression is an opt-out gate.**

| Mechanism                                           | Source of truth                                                                                                                                                                                    | Example trigger                                                                                                                                                                                        |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Duplicate-content guard** ("message suppression") | The org policy you `PUT` under [Message Suppression API](/api-reference/message-suppression) — window, channels, categories.                                                                       | A re-run campaign fires the identical promo body to the same number within the window → the second send reports `skipped`, reason `duplicate_content`.                                                 |
| **Consent suppression** (opt-out gate)              | The contact's recipient state — consent records and per-channel preference flags atomically written by STOP replies, the Preference Center, and the [Consent API](/compliance/consent-management). | The contact replied STOP to your SMS → every subsequent SMS to them is a refusal at the opt-out gate, on every channel scope the entry wrote.                                                          |
| **Suppression list** (imported block list)          | The suppression ledger — one row per `(address, channel-scope)` with a reason and source, populated by CSV import or written by opt-out entry points.                                              | You migrate from a legacy platform and [bulk-import](/compliance/opt-out-suppression) its "never contact" file → each row hard-blocks sends to that address, regardless of contact import or API call. |

Read the table top-down and the words stop colliding: one is a *policy*, one is *recipient state*, one is a *ledger*. None of the three replaces another.

## The three concepts side by side

**Duplicate-content suppression — metadata-based, relative suppression of identical bodies.**
The policy is a single opt-in object per organization. On every send the pipeline hashes the whitespace-normalized body text and claims the `(recipient, channel, body-hash)` marker as one compare-and-set; an identical body in flight within the window loses and is skipped. Manipulation primitives: `GET` / `PUT` / `DELETE /api/v1/message-suppression`, plus a dashboard wrapper.

**Consent suppression — per-channel gate driven by ledger state.**
Consent is recorded per contact with a lawful basis, and mirrored into per-channel flags the send path checks. An opt-out writes a fresh consent record, flips the flags, and (for a phone number reaching voice) writes a suppression row — see [Consent, opt-out, and suppression](/concepts/consent-and-suppression-model). The gate is a refusal, not a skip: direct sends get `422 RECIPIENT_OPTED_OUT`; campaign sends to opted-out recipients are skipped at the recipient-list level.

**Suppression list — per-row, per-channel, CSV-imported compliance block list.**
The same ledger of `(address, channel-scope)` rows powers both the migrations you bulk-import (`POST /compliance/suppression-list/import`) and the rows an opt-out writes through its own entry point. Scope defaults (`all` for phone-type addresses, `email` for email addresses) and per-row overrides are documented in [Opt-Out & Suppression Lists](/compliance/opt-out-suppression).

Two of these land in the *same* underlying ledger — that is why the console renders the consent inspector and the import wizard next to each other — while the duplicate-content guard is a separate Redis-backed marker store. "Suppressed" in an audit most often means "blocked by a suppression-list row"; which of the three did the work is recorded on the message outcome and in the recipient's consent history.

## Where each sits in the pipeline

Each outbound send walks the admission chain in a fixed order (the complete chain — wallet posture, quiet hours, throughput — is in [Outbound send gating](/concepts/send-gating-and-quiet-hours)):

1. **Opt-out / compliance gate** — consent suppression and the suppression list both land here. A recipient whose flags or ledger rows block the channel is refused first; nothing downstream ever runs for them.
2. **Duplicate-content suppression** — the message-suppression policy this page organizes. Runs only for recipients who cleared the gate, and skips an identical re-body without burning quota.
3. **Frequency cap** — the per-channel count axis ("how many sends in N hours"), consulted only after suppression has had its say; a suppressed duplicate never consumes a cap slot.
4. **Dispatch** — the message is handed to the channel provider.

Because the gate comes first, **pre-gate ordering of the opt-out checks means supplements never apply to a blocked recipient**: you cannot suppress-or-cap your way around an opt-out, and a skipped duplicate can only ever occur for a contact who is fully eligible to send to.

## Why the names collide in the dashboard

The console hosts all three under Settings, and two of them both say "suppression":

* **Settings → Message suppression** manages the duplicate-content policy — the content-hash guard on this page — as a thin wrapper over the same `GET` / `PUT` / `DELETE /api/v1/message-suppression` route the API exposes.
* **Settings → Opt-out lists & compliance** is the compliance surface: suppression-chain entries and the CSV import/export wizard operate on the *suppression list* ledger, the second mechanism.

A third surface, the consent inspector under Audience, shows the consent-record ledger the opt-out gate reads. If a search for "suppression" lands you in the wrong console, the disambiguation above — policy vs recipient state vs ledger — is the faster route to the right one than reading three guides.

## Propose or refuse — choosing the right mechanism

* **Propose the suppression list** for compliance-owned runbooks: migrating a legacy "never contact" export, onboarding a litigator-scrub file, honouring a partner's unsubscribe feed. Its import is rate-limited, deduplicated, and dry-run-able; export it back out when legal asks for the ledger.
* **Refuse the suppression list** for consent-primacy questions. "Why was this contact blocked?" and "under which basis did they opt back in?" are questions about the **consent ledger** — answer them from consent records and the recipient state, not from CSV rows. Re-messaging a suppressed contact without a documented fresh consent event is what the re-consent semantics exist to prevent.
* **Propose message suppression** when campaigns, flows, or retry logic can double-fire the same body and you would rather drop the duplicate silently than have a customer receive it twice. Keep it scoped to marketing categories so OTPs and receipts are never held back.
* **Refuse message suppression** as a substitute for honouring an opt-out. It deduplicates intended sends; it does not block a channel, and a contact who said STOP must be refused at the gate — not kept eligible and occasionally deduped.

## See also

* [Message suppression guide](/guides/message-suppression) — operating the duplicate-content policy end-to-end
* [Message Suppression API](/api-reference/message-suppression) — the policy schema and recipes
* [Opt-Out & Suppression Lists](/compliance/opt-out-suppression) — the suppression-list ledger, CSV import/export, and reversal semantics
* [Consent, opt-out, and suppression model](/concepts/consent-and-suppression-model) — the recipient-state stores the opt-out gate reads
* [Consent inspector](/guides/audience-consent-inspector) — per-contact consent records and destination verdicts
* [Outbound send gating](/concepts/send-gating-and-quiet-hours) — the full admission-chain ordering
* [Opt-outs API](/api-reference/optouts) — per-channel consent and blocking endpoints
