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
- 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
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
| 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
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
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
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:
| 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. |