Suppressions
Manage suppression lists to prevent sending to invalid, unsubscribed, or complained addresses
The suppression list prevents emails from being sent to addresses that have bounced, unsubscribed, or filed complaints. MailLand manages suppressions automatically from bounce and complaint events, and you can add or remove entries manually through the API.
Suppression Types
| Type | Value | Description | Default Scope |
|---|---|---|---|
HardBounce | 1 | Permanent delivery failure | Global (always) |
SoftBounce | 2 | Temporary failure (30-day Marketing suppression, escalates only after ≥3 eligible bounces across ≥7 days) | Marketing (30-day expiry) |
Complaint | 3 | Recipient marked email as spam | Global (always) |
Unsubscribe | 4 | Recipient opted out | Depends on message type |
Manual | 5 | Added manually via API or dashboard | Any scope |
Invalid | 6 | Invalid email format | Global (always) |
SpamTrap | 7 | Known spam trap address | Global (always) |
RoleAddress | 8 | Role-based email (info@, admin@, etc.) | Global (always) |
Suppression Scopes
Scopes control which types of emails are blocked:
| Scope | Value | Behavior |
|---|---|---|
Global | 0 | Blocks all emails (transactional and marketing) |
Marketing | 1 | Blocks marketing emails; transactional emails still delivered |
Transactional | 2 | Blocks transactional emails only (rare) |
List | 3 | Blocks emails for a specific mailing list only |
Scope constraints:
HardBounce,Complaint,Invalid,SpamTrap,RoleAddress→ Global scope onlySoftBounce→ typically Marketing scopeUnsubscribe→ Global, Marketing, or List (not Transactional)Manual→ any scope
List Suppressions
GET https://api.mail.land/v1/transactional/suppressionsAuthenticate with Authorization: Bearer <token> or X-API-Key: <api key>.
curl https://api.mail.land/v1/transactional/suppressions \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
cursor | string | - | Opaque cursor from the previous page's nextCursor. Omit for the first page. |
limit | int | 50 | Items per page (max 100) |
search | string | - | Filter by email address |
type | SuppressionType | - | Filter by type |
scope | SuppressionScope | - | Filter by scope |
mailingListId | string | - | The mailing list's public id, resolved inside your tenant. An unknown, foreign or numeric id returns 404. |
fromDate | datetime | 90 days ago | Start date |
toDate | datetime | Now | End date |
sortBy | string | CreatedAt | Sort field |
sortDescending | bool | true | Sort direction |
{
"items": [
{
"id": "k3v9x2m8q1w7z4",
"email": "[email protected]",
"suppressionType": "hardBounce",
"scope": "global",
"mailingListId": null,
"mailingListName": null,
"expiresAt": null,
"reason": "550 5.1.1 The email account does not exist",
"bounceType": "Hard",
"bounceCategory": "invalid_recipient",
"bounceCount": 1,
"lastBounceAt": "2026-02-17T12:00:00Z",
"unsubscribeSource": null,
"campaignId": null,
"subscriberId": null,
"source": "webhook",
"notes": null,
"createdAt": "2026-02-17T12:00:01Z",
"isLocked": false,
"lockedReason": null
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}mailingListId, campaignId and subscriberId are the related resource's public id, resolved inside your tenant: never the internal numeric row id. Each is null when the entry has no such link, or when the linked resource has since been deleted.
Suppression Stats
Get a summary of your suppression list:
GET https://api.mail.land/v1/transactional/suppressions/statscurl https://api.mail.land/v1/transactional/suppressions/stats \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"totalCount": 5000,
"globalCount": 3000,
"marketingCount": 1500,
"transactionalCount": 200,
"listCount": 300,
"hardBounceCount": 2000,
"softBounceCount": 1500,
"complaintCount": 500,
"unsubscribeCount": 700,
"manualCount": 200,
"invalidCount": 50,
"spamTrapCount": 30,
"roleAddressCount": 20,
"expiringCount": 85,
"lastSuppression": "2026-02-17T12:00:01Z"
}The expiringCount shows soft bounces that will expire within the next 7 days.
Check if an Email is Suppressed
Single check
GET https://api.mail.land/v1/transactional/suppressions/[email protected]&messageType=Marketingcurl "https://api.mail.land/v1/transactional/suppressions/[email protected]&messageType=Marketing" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."| Parameter | Type | Default | Description |
|---|---|---|---|
email | string | - | Email address (required) |
messageType | string | Marketing | Marketing or Transactional |
mailingListId | string | - | The mailing list's public id, resolved inside your tenant. An unknown, foreign or numeric id returns 404. |
{
"email": "[email protected]",
"isSuppressed": true,
"messageType": "Marketing"
}Bulk check
Check up to 1,000 emails at once:
POST https://api.mail.land/v1/transactional/suppressions/check-bulkcurl -X POST https://api.mail.land/v1/transactional/suppressions/check-bulk \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"emails":["[email protected]","[email protected]","[email protected]"],"messageType":"Marketing","mailingListId":null}'{
"emails": ["[email protected]", "[email protected]", "[email protected]"],
"messageType": "Marketing",
"mailingListId": null
}{
"suppressedEmails": ["[email protected]"]
}Add a Suppression
POST https://api.mail.land/v1/transactional/suppressionscurl -X POST https://api.mail.land/v1/transactional/suppressions \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","suppressionType":"Manual","scope":"Global","reason":"Customer requested removal from all lists","notes":"Ticket #4521"}'{
"email": "[email protected]",
"suppressionType": "Manual",
"scope": "Global",
"reason": "Customer requested removal from all lists",
"notes": "Ticket #4521"
}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
email | string | Yes | - | Email address (max 255 chars) |
suppressionType | string | No | Manual | Suppression type |
scope | string | No | Global | Suppression scope |
mailingListId | string | No | - | The mailing list's public id, resolved inside your tenant. Required if scope is List; an unknown, foreign or numeric id returns 404. |
reason | string | No | - | Reason (max 500 chars) |
notes | string | No | - | Internal notes |
Returns 201 Created with the full suppression object. The Location header is
/v1/transactional/suppressions: the list route, since there is no get-by-id endpoint. Use the
body's id field to identify the created suppression, and the List or
Check endpoints to look it up.
Bulk Add
Add up to 1,000 suppressions at once:
POST https://api.mail.land/v1/transactional/suppressions/bulkcurl -X POST https://api.mail.land/v1/transactional/suppressions/bulk \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"emails":[{"email":"[email protected]","suppressionType":"Manual","scope":"Global","reason":"Cleanup"},{"email":"[email protected]","suppressionType":"Manual","scope":"Marketing"}]}'{
"emails": [
{ "email": "[email protected]", "suppressionType": "Manual", "scope": "Global", "reason": "Cleanup" },
{ "email": "[email protected]", "suppressionType": "Manual", "scope": "Marketing" }
]
}{
"totalCount": 2,
"addedCount": 2,
"skippedCount": 0,
"skippedEmails": [],
"message": "Added 2 suppressions"
}Emails that already exist in the suppression list are skipped (not duplicated).
Import from CSV
From text content
POST https://api.mail.land/v1/transactional/suppressions/importcurl -X POST https://api.mail.land/v1/transactional/suppressions/import \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"csvContent":"[email protected]\[email protected]\[email protected]","defaultReason":"Imported from legacy system","suppressionType":"Manual","scope":"Global"}'{
"csvContent": "[email protected]\n[email protected]\n[email protected]",
"defaultReason": "Imported from legacy system",
"suppressionType": "Manual",
"scope": "Global"
}From file upload
POST https://api.mail.land/v1/transactional/suppressions/import-filecurl -X POST "https://api.mail.land/v1/transactional/suppressions/import-file?scope=List&mailingListId=123" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-F "[email protected]"scope and mailingListId are query parameters, not form fields: a form field with either name is silently ignored, so a List-scope import sent as a form field fails with 400. mailingListId is the list's public id, resolved inside your tenant; an unknown, foreign or numeric id returns 404.
Upload a .csv file (max 5 MB) with email addresses separated by commas or newlines. A header row containing "email" is automatically skipped.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
file | file (multipart form field) | CSV file (max 5 MB, .csv extension required) |
scope | string (query) | Suppression scope (default: Global) |
mailingListId | string (query) | The mailing list's public id, resolved inside your tenant. Required if scope is List; an unknown, foreign or numeric id returns 404. |
{
"totalRows": 1000,
"importedCount": 950,
"skippedCount": 40,
"invalidCount": 10,
"invalidEmails": ["not-an-email", "missing-domain@", "..."],
"errors": [],
"message": "Imported 950 emails. 40 already existed. 10 invalid."
}The invalidEmails list shows up to 10 invalid entries. Already-existing emails are counted as skippedCount, not errors.
Export Suppressions
Download your suppression list as CSV:
GET https://api.mail.land/v1/transactional/suppressions/exportcurl https://api.mail.land/v1/transactional/suppressions/export \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-o suppressions.csv| Parameter | Type | Description |
|---|---|---|
type | SuppressionType | Filter by type |
scope | SuppressionScope | Filter by scope |
mailingListId | string | The mailing list's public id, resolved inside your tenant. An unknown, foreign or numeric id returns 404. |
Returns a CSV file with columns: email, type, scope, mailing_list, reason, bounce_count, source, created_at, expires_at. Limited to 100,000 rows.
Remove a Suppression
By ID
DELETE https://api.mail.land/v1/transactional/suppressions/{id}curl -X DELETE https://api.mail.land/v1/transactional/suppressions/k3v9x2m8q1w7z4 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."By email
DELETE https://api.mail.land/v1/transactional/suppressions/[email protected]curl -X DELETE "https://api.mail.land/v1/transactional/suppressions/[email protected]" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."| Parameter | Type | Description |
|---|---|---|
email | string | Email to unsuppress (required) |
scope | SuppressionScope | Remove only for this scope |
mailingListId | string | Remove only for this mailing list: its public id, resolved inside your tenant. An unknown, foreign or numeric id returns 404. |
Returns 204 No Content on success, 404 if not found.
Locked Suppressions
Certain suppressions cannot be deleted to protect your sender reputation and comply with anti-spam regulations:
| Locked Type | Reason |
|---|---|
Complaint | Spam complaint: compliance requirement |
SpamTrap | Known spam trap: deliverability protection |
Unsubscribe via FeedbackLoop | ISP feedback loop |
Unsubscribe via OneClick | RFC 8058 one-click unsubscribe |
Unsubscribe via ManualLink | User confirmed unsubscribe |
Unsubscribe via Preference | User preference center choice |
Attempting to delete a locked suppression returns:
{
"code": "SUPPRESSION_LOCKED",
"message": "Cannot delete: Spam complaint - compliance requirement",
"details": {
"lockedReason": "Spam complaint - compliance requirement"
}
}Deleting complaint-based suppressions and resending to those addresses will damage your sender reputation and may violate anti-spam laws. These suppressions are locked for your protection.
Unsubscribe Sources
When a recipient unsubscribes, the source is recorded:
| Source | Value | Description | Locked |
|---|---|---|---|
ListUnsubscribeHeader | 0 | RFC 8058 List-Unsubscribe header | No |
ListUnsubscribeMail | 1 | mailto: unsubscribe | No |
WebForm | 2 | Web unsubscribe page | No |
Api | 3 | API call | No |
Admin | 4 | Admin panel | No |
FeedbackLoop | 5 | ISP feedback loop | Yes |
OneClick | 6 | RFC 8058 POST one-click | Yes |
ManualLink | 7 | User confirmed via link | Yes |
Preference | 8 | Preference center choice | Yes |
Error Responses
| Status | Code | Description |
|---|---|---|
400 | INVALID_REQUEST | Validation failure (invalid email, scope, or type) |
400 | INVALID_EMAIL_FORMAT | Email address format is invalid |
400 | CONTENT_TOO_LARGE | CSV file exceeds 5 MB |
403 | SUPPRESSION_LOCKED | Cannot delete a locked suppression |
404 | RESOURCE_NOT_FOUND | Suppression not found, or a supplied mailingListId names no mailing list in your tenant |
Next Steps
- Bounces: understand bounce types and auto-suppression
- Deliverability Overview: monitor sender reputation
- Webhooks Events: receive
message.bouncedevents (suppression.added/suppression.removedare defined in the catalog but never emitted today)