> ## 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.

# List-Unsubscribe Header Posture for Email Deliverability

> RFC 2369 List-Unsubscribe and RFC 8058 one-click unsubscribe as a tenant-owned deliverability control — which message classes carry the header pair, what a one-click POST does to your suppression list, how it differs from the in-body footer link and reply-based STOP, and the pitfalls that get bulk senders blocked.

# List-Unsubscribe Header Posture for Email Deliverability

The `List-Unsubscribe` headers on an outbound email are the control
mailbox providers read first and auditors ask for second. Orbit
attaches the header pair on every outbound message and lands every
unsubscribe on the same suppression ledger — but the *posture*
decisions are **tenant-owned**: which message classes carry the
headers, how you treat one-click versus in-body opt-outs, and how the
suppression entries they write interact with your consent model.

This page is the dedicated manual for that posture. For the mailbox-
provider regime that made the headers mandatory at volume, see
[Gmail & Yahoo Bulk-Sender Requirements](/compliance/email-bulk-sender-requirements);
for the statutory content layer the headers sit next to, see
[US CAN-SPAM Compliance](/compliance/can-spam#list-unsubscribe-header-behavior).

<Note>
  Compliance controls on Orbit are **tenant-owned**. Orbit is the
  conduit and system of record; the header pair on your outbound mail
  and the suppression ledger it feeds are yours to configure, audit,
  and answer for. This page is posture guidance, not legal advice.
</Note>

***

## 1. Why the header pair matters

Two RFCs define the mechanism, and one mailbox-provider regime made
it a gate:

* **RFC 2369 — `List-Unsubscribe`** (1998) names where a recipient's
  mail client should send an opt-out: one or more URLs, typically an
  HTTPS endpoint plus a `mailto:` fallback. Gmail, Yahoo, and Apple
  Mail read this header to render their native "Unsubscribe" button.
* **RFC 8058 — `List-Unsubscribe-Post: List-Unsubscribe=One-Click`**
  (2017) is the signal on top: it authorizes the mailbox provider to
  POST to the header URL on the recipient's behalf, and the opt-out
  must **complete with no further interaction** — no confirmation
  page, no login, no second click.
* **The Gmail/Yahoo bulk-sender regime** (published October 2023,
  enforced from February 2024) turned the pair from a convenience
  into an acceptance rule: senders above 5,000 messages/day whose
  marketing mail lacks one-click unsubscribe are **rejected at the
  door**, not merely spam-foldered. The full regime is documented on
  [Gmail & Yahoo Bulk-Sender Requirements](/compliance/email-bulk-sender-requirements).

One-click versus in-body unsubscribe links serve different masters:

| Mechanism | Required by | What the recipient sees | What it must do |
| - | - | - | - |
| `List-Unsubscribe` + `List-Unsubscribe-Post` headers | Gmail/Yahoo bulk-sender regime | A native "Unsubscribe" button in the mail client | POST completes the opt-out with zero further interaction (RFC 8058) |
| In-body unsubscribe link in the footer | CAN-SPAM, CASL, Spam Act, and your template review | A visible link inside the message body | Land on a working opt-out target — a single click may complete it, and CAN-SPAM requires that |
| Both together | The deliverable state | Button for the mailbox provider, link for the statute | Both resolve to the same suppression ledger |

Keep both. A header-only posture fails the statutory content review
(CAN-SPAM requires a conspicuous in-message mechanism); a link-only
posture fails the mailbox-provider gate at bulk volume.

***

## 2. Where it sits in the tenant-owned stack

Orbit carries the mechanism; you own the classification and the
posture. The operating split:

* **Marketing / promotional email** — campaigns, newsletters,
  announcements, win-backs. **Carries the header pair, always.** This
  is the class the Gmail/Yahoo regime names, the class every statute
  with an unsubscribe clause names, and the class recipients complain
  about. Orbit attaches `List-Unsubscribe` and
  `List-Unsubscribe-Post` on every outbound message, and marketing
  traffic is where those headers are load-bearing: without them the
  bulk-sender gate rejects, and with them a recipient's one-click
  writes an `email`-scope suppression row instead of a spam complaint
  that scores against your domain.
* **Transactional / OTP email** — receipts, order confirmations,
  password resets, one-time codes, security alerts. **Exempt from
  marketing-unsubscribe requirements** under CAN-SPAM's transactional
  exemption, CASL's existing-business-relationship provisions, and the
  Gmail/Yahoo regime's own scoping (the header requirement is stated
  for promotional/marketing traffic). A transactional message is not
  expected to carry a marketing opt-out, and recipients cannot
  meaningfully "unsubscribe" from a password reset. Where you send
  transactional traffic, keep it structurally transactional — a
  receipt with a promotional upsell block reclassifies as commercial
  under CAN-SPAM's primary-purpose test and inherits the full
  unsubscribe obligation.

The tenant-owned posture decisions that follow:

1. **Classify before you send.** Whether a message is marketing or
   transactional determines which obligations attach. Orbit enforces
   suppression on both classes — a suppressed address is dropped
   before dispatch regardless — but a *no-unsubscribe-required*
   exemption exists only for genuinely transactional content.
2. **Do not strip the header from marketing traffic.** The headers
   are attached at the transport layer on every send; there is no
   supported posture in which your marketing mail leaves without them.
   A posture page exists because the *consequences* of the headers —
   suppression entries, audit events, complaint-rate effects — are
   yours to manage.
3. **Seed legacy opt-outs before the first campaign.** An unsubscribe
   captured on a previous platform still counts; bulk-import it
   (`POST /api/v1/email/suppressions/bulk-import`) so a recipient who
   already opted out does not re-receive and re-complain. See
   [Opt-Out & Suppression Lists](/compliance/opt-out-suppression).

***

## 3. What the header actually does

Three distinct opt-out surfaces exist on Orbit. They look alike to a
recipient and are very different in the ledger:

| Surface | Transport | Resulting ledger entry |
| - | - | - |
| **One-click header POST** (mailbox provider's Unsubscribe button) | Provider POSTs to the `List-Unsubscribe` HTTPS URL with `List-Unsubscribe=One-Click` | Token verified → `email`-scope suppression row for the recipient → `email.unsubscribed` audit event |
| **In-body footer link** | Recipient's browser GETs the unsubscribe URL merged from `{{unsubscribe_url}}` | Same endpoint — same suppression write and audit event |
| **Reply-based STOP** (SMS/WhatsApp parallel, drawn here for contrast) | Inbound keyword on the messaging channel | `all`-scope suppression on the identifier, written from the inbound keyword path — see [Consent vs Suppression Precedence](/compliance/consent-vs-suppression-model) |

Key properties of the email surfaces:

* **One endpoint, two doors.** The header POST and the footer link
  both land on Orbit's signed unsubscribe endpoint. The suppression
  row written is identical: scope `email`, with an
  `email.unsubscribed` audit entry appended. A recipient cannot
  unsubscribe twice and prove different outcomes — both doors write
  the same ledger.
* **The POST is interaction-free by contract.** RFC 8058 requires the
  opt-out to complete on the POST alone. Orbit's endpoint honors that:
  no confirmation page, no login, no second step sits between the
  provider's POST and the suppression write.
* **The mailto fallback is a fallback.** The `List-Unsubscribe` header
  also carries a `mailto:unsubscribe@your-domain.com` alternative for
  clients that do not speak one-click. The HTTPS URL is the path the
  regime measures; the mailto exists for client compatibility.
* **Unsubscribes live on the outbound path.** Routing your own
  inbound mail through [inbound parse](/guides/inbound-email-parse)
  is a separate surface; unsubscribe POSTs never touch your inbound
  routes.

The walk-through, end to end:

1. Recipient clicks the mail client's Unsubscribe button (header) or
   your footer link (in-body).
2. The client POSTs to the `List-Unsubscribe` URL with
   `List-Unsubscribe=One-Click` (or the browser follows the merged
   `{{unsubscribe_url}}`).
3. Orbit verifies the signed token, writes an `email`-scope
   suppression row, and appends an `email.unsubscribed` audit event.
4. Your next send to that address — campaign, contact import, or API
   call — is dropped at the pre-send gate with
   `422 RECIPIENT_OPTED_OUT`, and the consumed quota slot is refunded.

***

## 4. Configuring it in Orbit

There is **no per-send toggle and no workspace switch for the header
pair** — attaching `List-Unsubscribe` and `List-Unsubscribe-Post` is
transport behavior on every outbound email, not a setting you flip.
What you configure is everything around it:

1. **The in-body footer is template work.** Keep an unsubscribe link
   and your physical postal address in a shared footer block so every
   campaign template carries both. The merge tag
   `{{contact.unsubscribeUrl}}` resolves at dispatch — see the
   worked request in
   [US CAN-SPAM Compliance](/compliance/can-spam#list-unsubscribe-header-behavior).
   A template that ships without the footer is a send-gate at the
   mailbox provider, not an Orbit error you will see locally.
2. **SMTP-relayed mail is identical.** Messages submitted over the
   [SMTP relay](/guides/smtp-send-email) enter the same pipeline, so
   the header pair, suppression gate, and audit ledger apply with no
   extra integration. If you inject your own `List-Unsubscribe`
   header from a thin client, the relay's pipeline-level value is the
   one mailbox providers act on — send through the pipeline rather
   than around it.
3. **Verify with a canary send before a new segment launches.**
   Send one message to a seed Gmail address and inspect the raw
   headers: both `List-Unsubscribe` and
   `List-Unsubscribe-Post: List-Unsubscribe=One-Click` present. The
   full pre-flight sequence is the worked checklist on
   [Gmail & Yahoo Bulk-Sender Requirements](/compliance/email-bulk-sender-requirements).
4. **Seed and export the ledger.** Bulk-import legacy opt-outs
   before migrating volume, and export the suppression ledger
   (`channel=email`) when an auditor asks for the trail the one-click
   flow feeds — both flows are on
   [Consent & Suppression Export](/compliance/consent-suppression-export).

***

## 5. How it composes with consent and suppression

The header pair is one *entry point* into two ledgers that already
document each other:

* **The suppression ledger is the enforcement side.** A one-click or
  footer-link unsubscribe writes an `email`-scope suppression row,
  and the pre-send gate is fail-closed for entries that exist — the
  dispatch drop happens regardless of any consent record. The scope
  model, the import/export flows, and deliberate un-suppression are
  on [Opt-Out & Suppression Lists](/compliance/opt-out-suppression).
* **The consent ledger is the record side.** The same unsubscribe
  writes an `opted_out` consent row scoped to `email` with source
  `unsubscribe_link`, visible in `GET /compliance/consent/history`
  alongside API revocations, preference-center changes, and verbal
  objections — one revocation trail an auditor reads as a single
  sequence. See
  [Consent Management](/compliance/consent-management).
* **Scope isolation is the compositional rule.** An email-scope
  suppression from `List-Unsubscribe` blocks email and only email;
  it does not touch an `opted_in` SMS or WhatsApp grant for the same
  contact. The full precedence matrix — which suppression scope beats
  which consent record, and when transactional classes bypass under a
  contractual basis — is defined on
  [Suppression vs Consent Precedence Model](/compliance/consent-vs-suppression-model).
* **The statues-and-regimes map closes the loop.** CAN-SPAM, CASL,
  and the Spam Act each name the same unsubscribe surface from their
  own content side; the country pages link into this header behavior
  rather than re-defining it.

***

## 6. Common pitfalls

1. **Assuming the footer link satisfies the mailbox-provider gate.**
   It does not. The in-body link satisfies CAN-SPAM's content
   requirement and the template reviewers; the bulk-sender regime
   checks the *header pair*, sampled on every marketing message.
   Orbit guarantees header presence at the transport layer, but if
   you route marketing traffic around the pipeline — a hand-rolled
   relay, a raw provider integration — you re-own the gate.
2. **Treating a one-click unsubscribe as a complaint.** It is the
   opposite of a complaint: the recipient chose the clean exit the
   regime wants them to have. A rising unsubscribe rate with a flat
   complaint rate is the healthy direction; a rising complaint rate
   (`GET /api/v1/email/suppressions/reputation`, ceiling **0.30%** in
   Postmaster Tools, healthy target **0.10%**) is what the regime
   punishes. Suppression of a complainer stops recurrence — it does
   not un-count the complaint already scored.
3. **Receiver-side auto-unsubscribe you never observe on your side.**
   Gmail surfaces an "Unsubscribe" action directly from the header
   pair and Yahoo likewise; the POST arrives at Orbit's endpoint and
   becomes a suppression row automatically. The pitfall is accounting:
   if your own warehouse counts "unsubscribes" only from form posts or
   a preference center, the provider-POST flow is invisible to you.
   Reconcile against the suppression ledger or the
   `email.unsubscribed` audit trail, not against your own form events.
4. **Suppressing scope confusion.** A recipient who unsubscribes from
   email still consents to SMS; sending them an SMS is not a
   violation, and *assuming* it is leads to wrongly fencing contacts.
   Conversely, an inbound SMS `STOP` suppresses scope `all` — a much
   wider fence than the email header ever writes. Read the scope on
   the row before you reason about what is blocked
   ([precedence matrix](/compliance/consent-vs-suppression-model)).
5. **Deleting suppression to "re-engage."** Un-suppression is a
   deliberate, audited action (`DELETE /api/v1/email/suppressions/:id`),
   and a recipient who unsubscribed via the header and is re-mailed
   typically re-complains — which scores against your domain under the
   bulk-sender regime rather than just re-suppressing. Treat removal
   as a re-consent decision, not a list-hygiene shortcut.
6. **No verifiable proof when an auditor asks.** The ledger answers
   it: the suppression row (scope, timestamp, source), the
   `email.unsubscribed` event on the audit trail, and the exported CSV
   of the email-scoped slice. Build the export into your evidence
   binder rather than reconstructing it from mail logs — the export
   run itself is audited, so the trail an auditor receives is
   provably the one the platform enforced.

***

## Related references

* [Gmail & Yahoo Bulk-Sender Requirements](/compliance/email-bulk-sender-requirements)
  — the mailbox-provider regime that made the header pair mandatory
  at volume; four obligations mapped to Orbit surfaces.
* [US CAN-SPAM Compliance](/compliance/can-spam) — the statutory
  content layer; names the same headers from the in-body side.
* [Opt-Out & Suppression Lists](/compliance/opt-out-suppression) —
  the ledger one-click unsubscribes write, and its import/export
  flows.
* [Consent Management](/compliance/consent-management) — the consent
  ledger the same event records against.
* [Suppression vs Consent Precedence Model](/compliance/consent-vs-suppression-model)
  — which scope beats which grant when both exist for one contact.
* [Send outbound email over SMTP](/guides/smtp-send-email) — relayed
  mail enters the same pipeline and inherits the same posture.
* [Email](/channels/email) — the channel surface: domain setup,
  suppression lifecycle, reputation endpoint, and the error catalog.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.