Both end in the same place: the recipient’s email preference for that target, switched off.
The header alone is a complete unsubscribe. You do not have to build anything — the in-body link is an addition you make when you want the way out to be visible in the message itself, and it is worth making for anything a recipient might describe as promotional.
The one-click header is automatic
Bodhveda attachesList-Unsubscribe and List-Unsubscribe-Post headers to every outbound email, and hosts the page they point at. You do not call anything, configure anything, or put anything in your template — this surface is already done.
GETverifies the token and renders a confirmation page. It changes nothing.POSTperforms the unsubscribe. This is both what the confirmation button submits and what Gmail and Yahoo call directly for one-click.
The
GET is side-effect-free on purpose. Mail scanners, link prefetchers, and security appliances fetch every URL in a message, headers included. A mutating GET would unsubscribe recipients who never clicked anything.The in-body link is yours to build — on direct sends
Those same bulk-sender rules also want a visible unsubscribe link in the message body of promotional mail. Bodhveda does not give you one: the signed token above is built on the send path and goes straight into the header. It is never returned to you, and there is no endpoint that mints one. So the footer link points at a page you host, and that page calls set preference withmedium: "email" and enabled: false.
The only real problem to solve is that the page is reached from an inbox, where nobody is logged in. A bare ?user=123 would let anyone unsubscribe anyone, so the link needs a signed token of your own.
This works on direct sends, where you know the recipient at the moment you compose the email. On a broadcast you do not — you make one call and Bodhveda picks the audience — so there is no per-recipient link to embed. See Broadcasts rely on the header.
1. Sign a token
HMAC the recipient id with a secret only your server knows. No database row, nothing to expire.unsubscribe-token.ts
PURPOSE string in what you sign. It stops a token minted for unsubscribing from being replayed against some other feature that happens to sign the same recipient id with the same secret.
2. Put the link in the footer
3. Flip the preference on your page
enabled: false is idempotent — it upserts the same row every time. That is what makes it safe for a link prefetcher to hit your page, and it is why you can unsubscribe on page load rather than behind a confirmation button, if you would rather spend one click than two. Offer a Resubscribe button on the resulting page and a prefetch costs the recipient nothing.
Mark the page
noindex. It is a public URL carrying a token, and it has no business in a search index.Or just link to your settings screen
If your emails go to signed-in users and you would rather not host a token flow at all, link the footer to your own notification settings page. It is one line and it is honest. The trade is that it costs a login. A recipient who wants out and hits a login wall marks the message as spam instead, which is strictly worse for you than an unsubscribe — a complaint hurts your sending reputation, and Bodhveda unsubscribes them anyway.Broadcasts rely on the header
A broadcast that carries email has no in-body unsubscribe link, and cannot have one. You make a single send and Bodhveda resolves the audience during fan-out, so at the moment you write the HTML there is no recipient to build a link for — and by the time there is, you are not in the loop. Your own signed token cannot close this gap either, for the same reason. This is not a degraded experience. Bodhveda builds a genuine per-recipient signed URL for every broadcast email and attaches the sameList-Unsubscribe headers it attaches to direct mail, so every recipient gets a working one-click unsubscribe in their mail client. The header is doing the whole job, and it is the job that Gmail and Yahoo actually check.
It holds up because broadcast email is not a bulk-mail channel here. The fan-out is capped at 100 recipients per broadcast by default, while the bulk-sender rules that expect a visible body link start at thousands of messages a day. A capped, target-scoped broadcast to the people watching one thread is not the thing those rules were written for.
What unsubscribing actually does
Every path — the hosted one-click page, your own page, a spam complaint, a toggle in your settings UI — converges on the same write: a recipient-level preference for that(target, email), set to disabled.
That means:
- Subsequent sends to that target still succeed, but the email is recorded as
mutedwithfailure_reason: preference_disabled. You can see it on retrieve a notification and in the Console. - The recipient’s in-app notifications for the same target are untouched. Mediums are gated independently — unsubscribing from email is not going quiet.
- Your settings screen reflects it immediately, because it reads the same resolved preference.
enabled: true.
Unsubscribe is per target, not global
An unsubscribe switches off one target, not email as a whole. A recipient who unsubscribes from your daily digest still gets replies to their conversation threads. That is usually what you want — it is the difference between “stop this one thing” and “stop everything”. There is no single “all email off” switch. To offer one, disable each cataloged(channel, event) pair for that recipient. A topic: any recipient rule covers every topic under one channel and event with a single write, so the loop is over your catalog’s channel/event pairs, not over every resource id.
Mandatory targets refuse the unsubscribe
A mandatory catalog entry cannot be switched off — the write is refused with a400, from the hosted page and your own page alike. Password resets and security alerts are supposed to be undeclinable.
Email on a mandatory target therefore carries no List-Unsubscribe header at all. Bodhveda suppresses it deliberately: advertising one-click unsubscribe would put an Unsubscribe chip in the recipient’s mail client that fails when clicked, and a chip that does nothing is worse than no chip — the recipient walks away believing they opted out. No header is the honest signal that this mail is not optional.
Spam complaints unsubscribe too
When your email provider reports a complaint (the recipient hit “report spam”), Bodhveda disables that recipient’s email preference for that target automatically, exactly as an unsubscribe would. The complaint is also recorded on the delivery row, so you can see it. This is target-scoped, matching an explicit unsubscribe. It is not an address-level suppression across every target.Complaint handling depends on your provider’s webhook reaching Bodhveda. Configure it in your project’s email settings, or complaints will be invisible and the recipient will keep receiving mail they have already reported.