Skip to main content

Unsubscribe Management

Optail manages unsubscribe state at the platform level, not inside individual providers. When you switch providers, your suppression lists carry over automatically.

How It Works

  1. You create unsubscribe groups -- logical categories like "Marketing", "Product Updates", "Billing Notifications".
  2. You include an unsubscribeGroupId when sending -- Optail injects an HMAC-signed unsubscribe link into the email footer.
  3. Recipients click the link -- Optail verifies the HMAC token, creates a suppression record, and shows a confirmation page.
  4. Future sends check suppressions -- Before delivering, Optail checks if the recipient is suppressed for the email's unsubscribe group. Suppressed emails are silently skipped.

Creating Unsubscribe Groups

curl -X POST https://api.optail.io/v1/unsubscribe-groups \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing",
"description": "Weekly newsletter and promotional emails",
"isDefault": true
}'

Mark one group as isDefault to use it when no specific group is provided.

Group Examples

GroupDescriptionUse for
MarketingNewsletters, promotionstags: ["marketing"]
Product UpdatesFeature announcementstags: ["product"]
TransactionalOrder confirmations, receiptsUsually no unsubscribe group (required emails)

Sending with Unsubscribe

Include the unsubscribeGroupId in your send request:

await optail.send({
to: 'user@example.com',
from: 'hello@yourdomain.com',
subject: 'Weekly Newsletter',
templateId: 'newsletter-tpl-id',
variables: { ... },
unsubscribeGroupId: 'grp-uuid',
tags: ['marketing', 'newsletter'],
});

Optail automatically:

  1. Checks if the recipient is suppressed in the specified group
  2. If not suppressed, injects an unsubscribe footer before </body>:
    <div style="text-align:center;font-size:12px;color:#9ca3af;">
    <p>You received this email based on your subscription preferences.</p>
    <p><a href="https://api.optail.io/v1/unsubscribe/HMAC_TOKEN">Unsubscribe</a></p>
    </div>
  3. If the recipient is suppressed, returns status: "suppressed" and does not send

Unsubscribe links are signed with HMAC-SHA256 to prevent abuse. The token contains:

FieldDescription
orgIdOrganization ID
groupIdUnsubscribe group ID
emailRecipient email address
tsTimestamp of link generation

The token is verified when the recipient clicks the link. Invalid or tampered tokens show an error page.

Suppression Enforcement Across Provider Switches

Suppressions in Optail are stored as SHA-256 hashes of email addresses in your database, not inside any provider. This means:

  • Switching from SendGrid to Postmark? All your suppression lists carry over.
  • Adding a second provider for failover? The same suppressions apply to both.
  • Importing suppressions from an old provider? Use the bulk import endpoint.

Importing Existing Suppressions

If you are migrating from another platform, bulk-import your existing suppression list:

curl -X POST https://api.optail.io/v1/suppressions/import \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"emails": [
"unsub1@example.com",
"unsub2@example.com",
"bounced@example.com"
],
"unsubscribeGroupId": "grp-uuid"
}'

You can import up to 10,000 emails per request. Duplicates are silently skipped.

Checking Suppressions

Before sending a marketing campaign, you can check if a specific address is suppressed:

const result = await optail.checkSuppression('user@example.com');

if (result.suppressed) {
console.log(`User is suppressed in groups: ${result.groups.join(', ')}`);
}

Managing Suppressions Manually

Add a suppression

await optail.addSuppression('user@example.com', 'grp-uuid');

Remove a suppression

await optail.removeSuppression('user@example.com', 'grp-uuid');

Via the API

# Add
curl -X POST https://api.optail.io/v1/suppressions \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "unsubscribeGroupId": "grp-uuid", "source": "MANUAL"}'

# Remove
curl -X DELETE https://api.optail.io/v1/suppressions/SUP_ID \
-H "Authorization: Bearer ms_live_your_api_key"

Suppression Sources

Each suppression records how it was created:

SourceDescription
UNSUBSCRIBERecipient clicked the unsubscribe link.
BOUNCEHard bounce detected from provider webhook.
COMPLAINTSpam complaint detected from provider webhook.
MANUALAdded manually via API or dashboard.
IMPORTBulk imported.