Unsubscribe Management
Unsubscribe Management
Section titled “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
Section titled “How It Works”- You create unsubscribe groups — logical categories like “Marketing”, “Product Updates”, “Billing Notifications”.
- You include an
unsubscribeGroupIdwhen sending — Optail injects an HMAC-signed unsubscribe link into the email footer. - Recipients click the link — Optail verifies the HMAC token, creates a suppression record, and shows a confirmation page.
- 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
Section titled “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
Section titled “Group Examples”| Group | Description | Use for |
|---|---|---|
| Marketing | Newsletters, promotions | tags: ["marketing"] |
| Product Updates | Feature announcements | tags: ["product"] |
| Transactional | Order confirmations, receipts | Usually no unsubscribe group (required emails) |
Sending with Unsubscribe
Section titled “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:
- Checks if the recipient is suppressed in the specified group
- 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> - If the recipient is suppressed, returns
status: "suppressed"and does not send
HMAC-Signed Unsubscribe Links
Section titled “HMAC-Signed Unsubscribe Links”Unsubscribe links are signed with HMAC-SHA256 to prevent abuse. The token contains:
| Field | Description |
|---|---|
orgId | Organization ID |
groupId | Unsubscribe group ID |
email | Recipient email address |
ts | Timestamp 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
Section titled “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
Section titled “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
Section titled “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
Section titled “Managing Suppressions Manually”Add a suppression
Section titled “Add a suppression”await optail.addSuppression('user@example.com', 'grp-uuid');Remove a suppression
Section titled “Remove a suppression”await optail.removeSuppression('user@example.com', 'grp-uuid');Via the API
Section titled “Via the API”# Addcurl -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"}'
# Removecurl -X DELETE https://api.optail.io/v1/suppressions/SUP_ID \ -H "Authorization: Bearer ms_live_your_api_key"Suppression Sources
Section titled “Suppression Sources”Each suppression records how it was created:
| Source | Description |
|---|---|
UNSUBSCRIBE | Recipient clicked the unsubscribe link. |
BOUNCE | Hard bounce detected from provider webhook. |
COMPLAINT | Spam complaint detected from provider webhook. |
MANUAL | Added manually via API or dashboard. |
IMPORT | Bulk imported. |