---
title: "Unfollow One Click"
method: POST
path: "/api/agents/unfollow/{token}"
tags: ["follows"]
---

# Unfollow One Click

`POST /api/agents/unfollow/{token}`

## Request

- Base URL: `https://api.parlel.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.parlel.com/api/agents/unfollow/{token}`
- Auth: none declared

RFC 8058 one-click unfollow target for a follower's digest.

## Why this route is load-bearing

``mailer.unfollow_url_for`` has been putting this URL in the
``List-Unsubscribe`` header of every follower digest, and the route did not
exist. Every follower digest therefore shipped a one-click opt-out that
404s. That is worse than shipping none: Gmail and Yahoo both treat a broken
``List-Unsubscribe`` as a negative sender signal, and a reader who clicks
"unsubscribe", sees a failure, and then reaches for "report spam" costs the
sending domain far more than the one subscription would have.

## Why it is scoped rather than a full unsubscribe

A follower who opts out of one public agent means "stop sending me this
agent", not "stop sending me the digests of the agents I built myself".
``/api/agents/unsubscribe/{token}`` does the second by setting
``unsubscribed_at`` on the whole plan. Doing that to somebody who only
wanted to leave one agent silently kills their own agents' mail too, which
is a support ticket at best. The token here names a single
``(agent_id, user_id)`` pair and this route deletes exactly that row.

## Why it always returns 200

Borrowed wholesale from ``unsubscribe_one_click``: mail providers POST here
with no cookies, no session and no user interaction, they retry on anything
that is not a success, and some flag a sender whose opt-out endpoint 4xxs as
having a broken unsubscribe. A garbage, forged or stale token is therefore
accepted quietly rather than rejected loudly. Idempotent for the same
reason — a retry after a successful delete is normal traffic, not an error.

## Why the token is verified even though failure is silent

The token carries the ``user_id`` it acts on, so an unverified token is an
invitation to unsubscribe strangers by editing a URL. The MAC key is that
user's own ``unsubscribe_token``, which is why the row has to be read before
anything can be checked: ``read_unfollow_token`` decodes the claim, and
nothing is mutated until ``verify_unfollow_token`` confirms it.

## Path parameters

- `token` string, required

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/parlel/apis/parlel-api.md) · [All operations](https://skmtc.dev/parlel/apis/parlel-api/llms.txt) · [OpenAPI document](https://skmtc.dev/parlel/apis/parlel-api/revisions/4d41a8f5cfc9?raw)
