Questions · Updated 2026-09-28
How do I add an unsubscribe link to my emails?
Add an unsubscribe link to your emails by naming a topic_id on POST /emails, or by sending through POST /broadcasts; both add the RFC 8058 one-click unsubscribe headers. Create the topic with POST /topics. Transactional emails such as receipts and sign-in codes do not need one.
Add an unsubscribe link to your emails by naming a topic_id on POST /emails, or by sending the message as a broadcast with POST /broadcasts followed by POST /broadcasts/{id}/send. Both add the RFC 8058 one-click headers, List-Unsubscribe and List-Unsubscribe-Post, so a mailbox that supports them can offer its own unsubscribe control and a click on it is recorded here. Create the topic first with POST /topics. Transactional emails, such as receipts and sign-in codes, do not need an unsubscribe link, and sending them without one is correct.
Topics
POST /topics creates one kind of mail a person can leave. Its summary: "Create a subscription topic. default_subscribed=false makes it opt-in: silence means no." Naming that topic's id as topic_id on POST /emails does three things at once: it screens every recipient against what they have said about the topic, it sends on the marketing stream, and it adds the one-click headers pointing at an unsubscribe for that topic alone. The headers are minted when the send has one recipient and that recipient is a contact; a topic send to several recipients still goes, without them, because a header that unsubscribes the wrong person is worse than none. When every recipient has opted out, the send is refused with suppressed_recipient.
curl -sS -X POST https://api.agentisend.com/topics \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"yourdomain.com"}'201
{
"created_at": "2026-09-04T09:14:00Z",
"default_subscribed": true,
"description": "string",
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"name": "yourdomain.com",
"updated_at": "2026-09-04T09:14:00Z"
}PATCH /contacts/{id}/topics records what a contact said; its summary is "Record this contact’s answer for one or more topics. Answers are absolute — nothing is inferred from what is left out." GET /contacts/{id}/topics reads it back, and its summary adds that "A topic they never answered reports the topic default, and says so."
Broadcasts
A broadcast is one message to one segment. POST /broadcasts drafts it and POST /broadcasts/{id}/send sends it, and every message carries the one-click headers for its contact. The lint rule below points here: its fix is "Send via POST /broadcasts, which adds RFC 8058 headers automatically." A contact who has unsubscribed is skipped, and the broadcast's detail page names the rule that skipped them. Broadcasts has the rest.
Check before you send
POST /emails/lint runs without sending and reports no_unsubscribe_bulk when the to list is long enough to read as bulk and there is no List-Unsubscribe header. The finding's message is "Bulk send without one-click unsubscribe — Gmail/Yahoo require it and filter without it." List-Unsubscribe is not a header you can pass yourself: POST /emails refuses it in headers, because the send path writes it.
What an unsubscribe does
A one-click unsubscribe lands the address on the suppression list as a row scoped to marketing mail, so receipts and password resets to the same person still send. An API key cannot lift that row; How do I remove an address from the suppression list? says who can. Audience covers contacts, segments and topics in the console.