Docs/Getting started/Subscriptions and unsubscribe

Subscriptions and unsubscribe

Every send is transactional or marketing. Marketing email can always be unsubscribed from, per topic or altogether; transactional email always reaches the recipient.

v1 · beta

Email types

Transactional email is part of a service the recipient uses: receipts, booking confirmations, password resets, security notices. It carries no unsubscribe link and is stopped only by a hard bounce or a manual suppression. Marketing email is everything else — newsletters, product updates, promotions. It must link to {{@unsubscribeUrl}}, and it is also stopped by spam complaints and by opt-outs.

The type lives on the template: it is set from the email-type choice at generation and confirmed in the builder's Sending section. An API send may override it per request with type; campaigns are always marketing. An API send without type uses the template's type only when you set it (or the builder set it from the email-type chip); otherwise the send is transactional, so an integration built before email types existed keeps delivering service email without a code change. Templates that predate this release carry a type guessed from their footer, shown as such in the templates list; a guess is never used for API sends until you confirm it in the builder's Sending section.

Transactional sends ignore unsubscribes and spam complaints by design.

Only mark email transactional when the recipient expects it as part of a service they use. A newsletter sent as transactional reaches people who asked you to stop, which is a complaint waiting to happen.

Topics

Topics let a recipient stop one kind of marketing email and keep the rest. Every workspace starts with Newsletter, Product updates and Promotions; manage them under Audience → Topics. Each topic has a slug (newsletter, product-updates, promotions) that the API uses.

  • A campaign picks one topic in its Template section, prefilled from the template's default
  • A template has a default topic, used when an API send names none
  • A marketing send with no topic at all is general marketing: it skips only recipients who stopped all marketing email

Sends that name an archived or unknown topic are refused with TOPIC_NOT_FOUND.

How recipients unsubscribe

  • The footer link. Marketing templates must link to {{@unsubscribeUrl}}; a campaign cannot launch without it, and API sends render it per recipient. The page shows the one topic the email was sent under and one button. After confirming it offers Undo, the workspace's other marketing topics, and “Stop all marketing emails”. It never offers transactional email and cannot resubscribe anyone.
  • Gmail and Yahoo one-click. Marketing sends carry List-Unsubscribe and List-Unsubscribe-Post headers, so the Unsubscribe button in the mail client works and is recorded the same way.
  • Your ESP's own unsubscribe. Unsubscribe webhooks from the provider are mapped onto the message they belong to and recorded as an opt-out.
  • Your product. Call unsubscribeContact / POST /api/v1/contacts/unsubscribe from your own preferences page.

Each unsubscribe is recorded as an event on the message and shows on the contact's page and in the campaign's stats. Resubscribing happens only from the dashboard or the API, never through a link.

What blocks what

BlockTransactional sendMarketing send
Hard bounceblockedblocked
Manual suppressionblockedblocked
Spam complaintsentblocked
Opt-out from a topicsentblocked under that topic; other topics and general marketing are sent
Opt-out from all marketingsentblocked

Hard bounces, complaints and manual suppressions are delivery blocks (suppressed: true on a contact; details.kind: "suppression" on a refused send). Opt-outs are marketing opt-outs (optOuts on a contact; details.kind: "opt_out"). A refused send is recorded with a Suppressed status and does not count against your quota. Temporary bounces — a full mailbox, greylisting — block nothing.

In the API and SDK

FieldWhereMeaning
typesend request and responsetransactional or marketing. Omitted: the template's confirmed type, else transactional. Declare it on marketing sends. The response echoes what the server resolved
topicsend request and responseTopic slug for a marketing send; omitted: the template's default, else general marketing. Not allowed with type: "transactional" (400)
RECIPIENT_SUPPRESSED422 from senddetails.kind is suppression or opt_out, details.reason is HARD_BOUNCE, MANUAL, COMPLAINT, OPT_OUT_TOPIC (with details.topic) or OPT_OUT_ALL. The SDK exposes it as isOptedOut() and suppressionDetails()
optOutscontact responses[{ topic: slug | null, createdAt }]; null is all marketing. suppressed now means a delivery block only
unsubscribe / resubscribePOST /api/v1/contacts/unsubscribe, /resubscribe{ email, topic? }; omitted topic = all marketing. SDK: unsubscribeContact, resubscribeContact
typescript
// A receipt: delivered even to someone who unsubscribed from marketing
await client.send({
  to: 'maya@example.com',
  subject: 'Your receipt',
  template: 'receipt',
  type: 'transactional',
  idempotencyKey: `receipt-${order.id}`,
  variables: { total: order.total },
});

// A newsletter: skipped for anyone who stopped the newsletter or all marketing
await client.send({
  to: 'maya@example.com',
  subject: 'This month at Linen',
  template: 'newsletter',
  type: 'marketing',
  topic: 'newsletter',
  variables: { firstName: 'Maya' },
});

Integrating

  • Pass type: 'transactional' on every system send — receipts, confirmations, resets — so a marketing unsubscribe can never stop it. Do not rely on the template's type for these; the request wins.
  • After upgrading, open the templates list and review every template shown as guessed: confirm its type in the builder's Sending section, and give marketing templates a default topic.
  • Marketing templates need the {{@unsubscribeUrl}} link. Variable names starting with @ are reserved and rejected with 400, so it cannot be overridden.
  • Handle 422 with isOptedOut(): an opted-out marketing send is not an error to retry, and the same recipient still receives transactional email.
Provider-side lists still apply.

Some ESPs keep their own complaint list and may refuse a transactional send to someone who reported an earlier email as spam. That surfaces as a Failed message with the provider's error, not as RECIPIENT_SUPPRESSED.

Was this page helpful?