Suppressions API
Manage account-level suppressions and topics (suppression groups) that stop mail to bounced, complained or opted-out recipients.
Suppressions API
Suppressions stop mail to addresses that should not receive it. NorthRelay has two layers:
- Account-level suppressions block an address for your whole account. NorthRelay adds them automatically on hard bounces, spam complaints and "unsubscribe from all"; you can also add them yourself.
- Topics (stored as suppression groups) let a recipient opt out of one category of mail, such as "Product updates", while still receiving the rest.
To subscribe or unsubscribe a recipient with the right side effects (contact status, list membership, webhooks), use the Subscriptions API. The routes on this page manage the underlying records directly.
Scopes: suppressions:read for GET, suppressions:write for everything else, on both /suppressions/** and /suppression-groups/**.
How suppressions apply when you send
NorthRelay filters every recipient before the message is queued. Filtered recipients are dropped and do not count against your monthly quota.
| Blocked by | |
|---|---|
| Marketing (campaigns, marketing message streams) | Any account-level suppression; contact status UNSUBSCRIBED, BOUNCED, COMPLAINED or CLEANED; an opt-out of the topic the message is sent under |
| Transactional | Only Bounce and Complaint suppressions and contact status BOUNCED, COMPLAINED or CLEANED. Unsubscribes do not block receipts and password resets. |
Suppression reasons:
reason | Added when | Lifted by a subscribe call? |
|---|---|---|
Bounce | Hard bounce (5xx) reported by the receiving server | Never |
Complaint | Spam complaint via a feedback loop | Never |
Unsubscribe | The recipient unsubscribed from all mail (link, one-click, preference centre or API) | Only with "resubscribe": true |
Manual | You added it | Never; delete it yourself |
List Suppressions
GET /suppressionsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 25 | Items per page (max 100) |
reason | string | -- | Bounce, Complaint, Unsubscribe or Manual |
search | string | -- | Matches part of the email address |
Example Request
curl "https://app.northrelay.ca/api/v1/suppressions?reason=Bounce&limit=10" \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx"Example Response
{
"success": true,
"data": [
{
"id": "cmg7s0p00001qz8kab12cd34",
"email": "invalid@example.com",
"reason": "Bounce",
"details": {
"bounceCode": "550",
"bounceReason": "5.1.1 The email account that you tried to reach does not exist",
"messageId": "<20261003081500.a1b2c3@yourdomain.com>",
"recordedAt": "2026-10-03T08:15:00.000Z"
},
"createdAt": "2026-10-03T08:15:00.000Z"
}
],
"meta": { "page": 1, "limit": 10, "total_count": 24, "has_more": true }
}details is free-form and depends on how the suppression was created (for unsubscribes it records the method and campaignId).
Get a Suppression
GET /suppressions/{email}Returns the suppression for one address, or 404 RESOURCE_NOT_FOUND when the address is not suppressed. URL-encode the address. To see suppression, contact status, lists and topics together, use GET /subscriptions/{email}.
Add Suppression
POST /suppressionsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address to suppress |
reason | string | Yes | Bounce, Complaint, Unsubscribe or Manual |
details | object | No | Free-form notes, for example a support ticket number |
If the address is already suppressed, its reason and details are updated.
Example Request
curl -X POST https://app.northrelay.ca/api/v1/suppressions \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"email": "optout@example.com",
"reason": "Manual",
"details": { "ticket": "4521" }
}'Returns 201 with the suppression in data.
Adding an Unsubscribe suppression here does not change the contact's status or fire a webhook. To record an opt-out, prefer POST /subscriptions/unsubscribe.
Bulk Add or Remove
POST /suppressions/bulkAPI key only.
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | add or remove |
emails | string[] | Yes | 1–10,000 addresses |
reason | string | When action is add | Bounce, Complaint, Unsubscribe or Manual |
curl -X POST https://app.northrelay.ca/api/v1/suppressions/bulk \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"action": "add",
"reason": "Bounce",
"emails": ["bounce1@example.com", "bounce2@example.com"]
}'{ "success": true, "data": { "action": "add", "requested": 2, "added": 2, "updated": 0 } }updated counts addresses that were already suppressed with a different reason. With action: "remove" the response is { action, requested, removed }.
Remove Suppression
DELETE /suppressions/{email}curl -X DELETE https://app.northrelay.ca/api/v1/suppressions/invalid%40example.com \
-H "Authorization: Bearer nr_live_xxxxxxxxxxxx"{ "success": true, "data": { "email": "invalid@example.com", "removed": true } }Only remove a Bounce or Complaint suppression when you have confirmed the address is valid and wants your mail. Sending to addresses that bounced or complained damages your sender reputation and the shared sending IP.
Topics (Suppression Groups)
A topic is a category of mail that recipients can opt out of on its own. Each topic is a suppression group, and a member of the group is an address that opted out of that topic. "Subscribing" someone to a topic means removing them from the group.
Topics take effect on marketing mail when you send:
- a campaign with a subscription topic set,
- a campaign to a list that is tagged with the topic (
suppressionGroupIdon the list), - a marketing-stream API message with
"suppressionGroupId": "<topicId>"on the send request.
Recipients who opted out of the topic are skipped. Transactional mail ignores topic opt-outs. Recipients can manage published topics themselves on NorthRelay's hosted preference centre ({{preferences_url}}), or on your own page through GET / PATCH /subscriptions/{email}.
Prefer the Subscriptions API for opt-ins and opt-outs: POST /subscriptions/unsubscribe with scope: "topic" also removes the recipient from lists tagged with the topic and fires contact.unsubscribed. The member routes below only edit the group.
List topics
GET /suppression-groups| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 25 | Items per page (max 100) |
published | boolean | -- | true returns only topics shown on the hosted preference centre, in display order |
{
"success": true,
"data": [
{
"id": "cmg7t0p1c0003qz8k7h2d4pqr",
"name": "product-updates",
"description": "Release notes and feature announcements",
"isDefault": false,
"publicLabel": "Product updates",
"publicDescription": "New features and release notes, about twice a month.",
"isPublishedOnUnsub": true,
"sortOrder": 0,
"createdAt": "2026-09-01T10:00:00.000Z",
"updatedAt": "2026-09-01T10:00:00.000Z",
"_count": { "members": 12 }
}
],
"meta": { "page": 1, "limit": 25, "total_count": 1, "has_more": false }
}_count.members is the number of addresses that opted out.
Create a topic
POST /suppression-groups| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | 1–100 characters, unique in your account |
description | string | No | Internal description, max 500 characters |
isDefault | boolean | No | Mark as the default topic |
Get, update or delete a topic
GET /suppression-groups/{id}
PATCH /suppression-groups/{id}
DELETE /suppression-groups/{id}PATCH accepts name, description, isDefault, and the public fields recipients see:
| Field | Type | Description |
|---|---|---|
publicLabel | string | null | Name shown to recipients (max 120 characters) |
publicDescription | string | null | One-line explanation shown to recipients (max 500 characters) |
isPublishedOnUnsub | boolean | Show the topic on the hosted preference centre |
sortOrder | integer | Display order (0–10000) |
Deleting a topic deletes its opt-outs; those addresses become eligible for that mail again.
Topic opt-outs (members)
GET /suppression-groups/{id}/members
POST /suppression-groups/{id}/members { "email": "jane@example.com" }
DELETE /suppression-groups/{id}/members/{email}GET returns { email, createdAt } rows (paginated with page and limit). POST opts an address out (idempotent, returns 201). DELETE removes the opt-out. The older paths /suppression-groups/{id}/suppressions, /suppressions/{email} and /suppressions/bulk remain available.
Suppression Object Reference
| Field | Type | Description |
|---|---|---|
id | string | Unique suppression identifier |
email | string | Suppressed email address |
reason | string | Bounce, Complaint, Unsubscribe or Manual |
details | object | null | Free-form details |
createdAt | string | ISO 8601 creation timestamp |