Unsubscribe
Public, anonymous endpoints that power one-click email unsubscribe. Every broadcast email automatically includes an unsubscribe footer link and RFC 8058 List-Unsubscribe / List-Unsubscribe-Post headers pointing here — you never need to build your own unsubscribe flow for broadcasts.
Unlike the rest of the API, these endpoints live at the root of the API host (not under /v1), require no authentication, and respond with HTML pages intended for the recipient's browser or mail client. Each link carries a unique per-contact token.
Confirmation page
/unsubscribe?token={token}Renders an HTML confirmation page with an 'Unsubscribe me' button that POSTs back the same token. A GET never unsubscribes anyone, so inbox link-prefetchers can't accidentally opt a contact out.
Query parameters
| Parameter | Type | Description |
|---|---|---|
tokenrequired | string | Per-contact unsubscribe token embedded in the email link. |
Perform unsubscribe (one-click)
/unsubscribe?token={token}Performs the opt-out. This is also the RFC 8058 one-click target that mail clients invoke directly when the user presses their native Unsubscribe button.
curl -X POST "https://api.txtly.com.au/unsubscribe?token=CONTACT_TOKEN"Unsubscribing a contact does two things:
| Parameter | Type | Description |
|---|---|---|
unsubscribed flag | effect | The contact's unsubscribed flag is set to true, excluding them from all future broadcasts. |
suppression entry | effect | The email address is added to the team's suppression list with reason 'unsubscribe', blocking every send path (transactional, batch, workflow, and broadcast). |
Responses
Both endpoints always return 200 OK with an HTML page. Unknown or expired tokens receive a generic page — the endpoint never reveals whether a token (and therefore a contact) exists, and one-click mail clients expect a success response regardless. Repeating the POST for an already-unsubscribed contact is a no-op that shows the same "unsubscribed" confirmation.
Resubscribing
To opt a contact back in, set their unsubscribed flag back to false via PATCH /v1/contacts/{id} and remove the matching suppression entry via DELETE /v1/suppressions/{id}.