Unsubscribe links
Marketing mail needs a way for recipients to opt out, and bulk senders are required by Gmail and Yahoo to offer one-click unsubscribe. A recipient can take two paths: the unsubscribe button the mailbox provider renders from your List-Unsubscribe header, and a link in the message body. Bird wires up both on marketing sends, reports each as a webhook event, and acts on them by suppressing the address. This guide covers both paths, the hosted unsubscribe page behind them, the events Bird fires, and how suppression closes the loop.
Set the category first
Unsubscribes only mean something for mail a recipient can opt out of, so the first thing to get right is the category. A send is category: "marketing" by default, so marketing, newsletter, and announcement mail is treated correctly with no extra work: a recipient who opts out is suppressed with reason unsubscribe, which blocks marketing sends but still lets transactional mail (password resets, receipts) through. Set category: "transactional" explicitly for operational mail, so it is never gated by an unsubscribe and carries no opt-out affordance.
One-click List-Unsubscribe (RFC 8058)
The one-click mechanism is the unsubscribe button mailbox providers render in their own UI, driven by two headers on your message:
Exemple de code
List-Unsubscribe: <https://yourapp.com/unsubscribe?token=abc123>, <mailto:unsubscribe@yourdomain.com?subject=unsubscribe>
List-Unsubscribe-Post: List-Unsubscribe=One-ClickList-Unsubscribe lists where to send the opt-out: an HTTPS URL, a mailto:, or both. List-Unsubscribe-Post: List-Unsubscribe=One-Click is what makes it one-click (RFC 8058): the provider sends a plain POST to the HTTPS URL when the recipient taps unsubscribe, with no confirmation page. The endpoint must accept that unauthenticated POST and record the opt-out without requiring the recipient to log in or confirm; that is the contract Gmail and Yahoo check for.
On a marketing send Bird sets these headers for you, pointing at a Bird-managed opt-out endpoint, so the compliant one-click button appears with no work on your side. This is true however you send: a broadcast from the dashboard, or a marketing message through the API (POST /v1/email/messages), which is the default category. Because Bird owns the header on marketing mail, supplying your own List-Unsubscribe or List-Unsubscribe-Post on a marketing send is rejected with a 422. On a transactional send Bird adds no unsubscribe header, and you may set your own through the headers field if you have a reason to.
When a recipient uses the provider's button, Bird fires an email.list_unsubscribed event.
The in-body unsubscribe link
The other path is a visible unsubscribe link in the message body, the opt-out marketing mail is expected to carry on top of the header button. Bird adds one to your marketing sends automatically, in both the HTML and plain-text parts, so a recipient always has a link to click without you building or hosting anything. You are free to add your own link as well (for example to a preference center you host), and the platform link remains as the compliant floor.
Choosing where the link goes
By default the link arrives as a small footer appended to the end of the body. To place it yourself, put the reserved {{unsubscribe_url}} variable where the link belongs:
Exemple de code
<p>
You received this because you subscribed to our newsletter. You can {{unsubscribe_url}} at any
time.
</p>When the body contains {{unsubscribe_url}}, Bird renders the unsubscribe link there instead of appending the footer: in HTML, an anchor whose text is "unsubscribe"; in the plain-text part, the raw opt-out URL. The link is substituted into the outgoing copy only, so reading the message back through the API returns your original content with the variable intact.
When a recipient unsubscribes through the in-body link, Bird fires an email.unsubscribed event, distinct from email.list_unsubscribed so you can tell an in-body opt-out apart from a provider-button one.
The hosted unsubscribe page
Both paths terminate on a Bird-hosted confirmation page. The in-body link records the opt-out as part of the click and then lands there; the one-click button records it through the provider's POST. Loading the page by its URL alone records nothing, and the page offers a confirm button for the rare visit where no opt-out was recorded yet, so a shared or forwarded page link can't unsubscribe anyone by itself.
Brand it on the Unsubscribe page page (Email → Unsubscribe page) in the dashboard: set the sender name recipients see (it falls back to your organization name when unset) and the background, text, and button colors, with a live example link to preview the result. Suppression records created through this page carry origin: unsubscribe_link (the Suppressions guide covers the origin vocabulary).
The webhook events
Bird delivers both unsubscribe events to your webhook endpoint in the standard event envelope. Subscribe to them the same way you subscribe to any other email event; no separate unsubscribe webhook exists:
| Event | Fires when |
|---|---|
| email.unsubscribed | The recipient clicked the unsubscribe link in your message body. |
| email.list_unsubscribed | The recipient used the mailbox provider's one-click button (List-Unsubscribe). |
Both carry the identity base every email event carries (email_id, recipient_id, workspace_id, the recipient address and its recipient_role, plus the tags and metadata from the original send), so you can reconcile the opt-out against your own records without an extra lookup. Use these events to update preferences in your own system: flip the subscription off, log the opt-out, stop including the address in your sends. The full payload shapes and the rest of the email event catalog are in the events reference.
Suppression closes the loop
You don't have to act on the webhook to stop Bird from mailing an unsubscribed recipient again; Bird does it automatically. Both email.unsubscribed and email.list_unsubscribed add the address to your workspace suppression list with reason unsubscribe and applies_to: non_transactional:
- Future marketing sends to the address are rejected up front with email.rejected and rejection_reason: "recipient_suppressed".
- Future transactional sends still go through: an unsubscribe is a preference about marketing mail, not a dead address.
That makes the webhook events a mirror for your own database rather than the thing that protects your reputation; Bird already blocks the send. If you ever need to inspect or undo an unsubscribe, the suppression record carries source_email_id and source_recipient_id linking back to the message that caused it, and you can remove it through the suppressions API.
Next steps
- Categories: why marketing is what makes an unsubscribe take effect
- Suppressions: the list unsubscribes land on, and how to manage it
- Email events: the full email.unsubscribed / email.list_unsubscribed payloads and the rest of the catalog
- Gmail & Yahoo requirements: where one-click unsubscribe is required for bulk senders
- Webhooks: subscribing an endpoint, signature verification, and retries