Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Suppressions

A suppression is a "don't send to this address" marker. ScaiSend maintains three kinds automatically — bounces, spam reports, unsubscribes — and also supports suppression groups for per-topic opt-outs. This page describes what each kind means, how they're populated, and what happens when a send hits one.

The three kinds#

Kind When added Effect on future sends
Bounce Recipient MX returned a permanent failure, or an async DSN arrived Skipped unless mail_settings.bypass_bounce_management or mail_settings.bypass_list_management is set
Spam report A feedback-loop report arrived from an ISP (Gmail, Yahoo, etc.) Skipped unless mail_settings.bypass_spam_management or mail_settings.bypass_list_management is set
Unsubscribe Recipient clicked the unsubscribe link or used RFC 8058 one-click Skipped unless mail_settings.bypass_unsubscribe_management or mail_settings.bypass_list_management is set

All three lists are tenant-scoped. If address X bounces on tenant A, it's suppressed for A only.

Automatic vs manual#

The primary flow is automatic. ScaiSend watches SMTP responses, DSN bounces, and FBL reports, and adds addresses to the right list without any action on your part.

Manual adds exist for edge cases:

  • Migration from another provider. When you move from SendGrid/Mailgun/Postmark, import their suppression lists so you don't re-send to addresses that bounced there.
  • External reports. A user called support to opt out. Record it via API so your next send skips them.
  • Pre-emptive blocks. You have a list of known bad addresses from a list-cleaning service.
bash
1
2
3
4
5
# Manual bounce add
curl -X POST https://scaisend.scailabs.ai/v3/suppression/bounces \
  -H "Authorization: Bearer $SCAISEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "invalid@example.com", "reason": "Imported from SendGrid, hard bounce 2026-03-01"}'

Suppression groups (ASM)#

A suppression group lets recipients unsubscribe from a specific kind of email instead of all email. Typical groups:

  • Marketing (promotions, announcements)
  • Product Updates (release notes, feature launches)
  • Newsletter (weekly digest)
  • Transactional (receipts, password resets — almost never want this opt-outable)

Each group has a numeric ID. When you send, specify the group:

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "personalizations": [{"to": [{"email": "user@example.com"}]}],
  "from": {"email": "hello@mail.example.com"},
  "subject": "Newsletter #42",
  "content": [{"type": "text/html", "value": "<html>..."}],
  "asm": {
    "group_id": 123,
    "groups_to_display": [123, 456, 789]
  }
}

The recipient sees a preference page (not just a blunt "unsubscribe") listing the groups in groups_to_display. They can opt out of Newsletter while staying subscribed to Receipts.

Creating a group#

bash
1
2
3
4
curl -X POST https://scaisend.scailabs.ai/v3/asm/groups \
  -H "Authorization: Bearer $SCAISEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Newsletter", "description": "Our weekly digest", "is_default": false}'

Response includes the numeric id — that's what goes in asm.group_id on future sends.

Group unsubscribe vs global unsubscribe#

The unsubscribe link in a grouped send defaults to group-scoped. The recipient stays subscribed to other groups. There's also a "Unsubscribe from all" link that adds them to the global unsubscribe list, blocking every future send from this tenant.

Events emitted:

Event When
group_unsubscribe Recipient unsubscribed from a specific group
group_resubscribe Recipient re-subscribed to a group (via a preference page)
unsubscribe Recipient hit "Unsubscribe from all" or the List-Unsubscribe header

Bypass flags#

Some sends must go through regardless of suppression state — password resets, account security alerts, legal notices. Use the bypass flags in mail_settings:

Flag What it bypasses
bypass_list_management All of the below combined
bypass_bounce_management Bounce list
bypass_spam_management Spam-report list
bypass_unsubscribe_management Unsubscribe list (global and group)
json
1
2
3
4
5
6
7
8
9
{
  "personalizations": [{"to": [{"email": "user@example.com"}]}],
  "from": {"email": "security@mail.example.com"},
  "subject": "Password reset",
  "content": [{"type": "text/plain", "value": "Reset link: ..."}],
  "mail_settings": {
    "bypass_list_management": {"enable": true}
  }
}

Use sparingly. Bypassing ignores real deliverability signals. A hard-bounced address won't magically accept your password reset because you bypassed the check. The correct use is for legitimate transactional mail where the recipient must receive it (regulatory, security), not as a hack around user preferences.

You still can't send to an invalid address. SMTP will reject it; the message will end in bounced state.

Managing suppressions via API#

Full CRUD is available. The endpoints track SendGrid's:

Bounces#

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# List
curl "https://scaisend.scailabs.ai/v3/suppression/bounces?limit=50" \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

# Delete one (allow future sends to this address)
curl -X DELETE https://scaisend.scailabs.ai/v3/suppression/bounces/user@example.com \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

# Bulk import from CSV
curl -X POST https://scaisend.scailabs.ai/v3/suppression/bounces/import \
  -H "Authorization: Bearer $SCAISEND_API_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @old-bounces.csv

Spam reports#

bash
1
2
3
4
5
curl https://scaisend.scailabs.ai/v3/suppression/spam_reports \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

curl -X DELETE https://scaisend.scailabs.ai/v3/suppression/spam_reports/user@example.com \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

Global unsubscribes#

bash
1
2
3
4
5
6
curl https://scaisend.scailabs.ai/v3/asm/suppressions/global \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

# Is a specific address globally unsubscribed?
curl https://scaisend.scailabs.ai/v3/asm/suppressions/global/user@example.com \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

Group suppressions#

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# List suppressions in a group
curl https://scaisend.scailabs.ai/v3/asm/groups/123/suppressions \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

# Add (manual opt-out)
curl -X POST https://scaisend.scailabs.ai/v3/asm/groups/123/suppressions \
  -H "Authorization: Bearer $SCAISEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"recipient_emails": ["opt-out@example.com"]}'

# Remove (resubscribe)
curl -X DELETE https://scaisend.scailabs.ai/v3/asm/groups/123/suppressions/opt-out@example.com \
  -H "Authorization: Bearer $SCAISEND_API_KEY"

Full endpoint list in Suppressions Reference.

What gets recorded when a send is suppressed#

A send that hits a suppression:

  1. Does not get handed to SMTP — no network I/O, no recipient contact.
  2. Is recorded as a message with status FAILED (or skipped, depending on version; confirm with GET /v3/messages/{id}).
  3. Emits a dropped event with reason suppressed.
  4. Increments the dropped counter in daily stats.

So you can audit suppression activity via the event stream and stats — you won't be silently dropping mail without any record.

What's next#

  • Tracking — how subscription tracking populates unsubscribes.
  • Bounce Handling — how DSNs become bounce suppressions.
  • Feedback Loops — how ARF reports become spam-report suppressions.
Updated 2026-05-17 01:33:26 View source (.md) rev 1