Suppression
Hard-blocking an address, account-wide.
The Suppression object 4 fields
The blocked address, normalised to lowercase.
Free-text audit note. Nothing branches on it; re-suppressing replaces it.
List suppressed addresses
Every address on the account's suppression list — a hard send block that applies regardless of any contact's subscription state, and even to addresses with no contact record. The whole list is returned in one page; there is no pagination on this endpoint today. Requires suppression:read.
This is distinct from unsubscribing (a preference on a contact) and from a per-sender block (an address a contact bounced on for one identity). Suppression is account-wide and address-level.
A page of Suppression objects, under data.
The full suppression list.
The request failed validation, or a referenced record was rejected.
The tenant slug, or the record the path names, does not exist.
curl -X GET "https://api.sonarsend.com/t/acme/api/suppressions" \ -H "X-API-Key: $SONARSEND_API_KEY"
const res = await fetch('https://api.sonarsend.com/t/acme/api/suppressions', {
method: 'GET',
headers: { 'X-API-Key': process.env.SONARSEND_API_KEY },
});
const data = await res.json();{
"data": [
{
"tenant_id": "9c21895d-57f0-4a15-a1df-4dc6835d4f80",
"email": "jamie@example.com",
"reason": "string",
"created_at": "2026-01-15T09:30:00.000Z"
}
],
"next_cursor": "eyJpZCI6IjljMjE4OTVkIn0",
"has_more": true
}Suppress an address
Adds an address to the suppression list. Requires suppression:write. The address is lowercased and trimmed on the way in, so Blocked@Example.com and blocked@example.com are the same entry.
Keyed on (tenant, email), so re-suppressing an address already on the list upserts rather than erroring — but note it replaces the stored reason, so re-posting without one clears the previous note. reason is free text for your own auditing; nothing branches on it. Returns 201 with the row.
This blocks the address; it does not change any contact's subscription status. To suppress a contact AND mark them unsubscribed, use the bulk endpoint with contact IDs.
Address to block. Normalised to lowercase.
Optional free-text audit note. Replaces any existing note on re-suppress.
The Suppression object.
The address was suppressed.
The request failed validation, or a referenced record was rejected.
The tenant slug, or the record the path names, does not exist.
curl -X POST "https://api.sonarsend.com/t/acme/api/suppressions" \
-H "X-API-Key: $SONARSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jamie@example.com",
"reason": "string"
}'const res = await fetch('https://api.sonarsend.com/t/acme/api/suppressions', {
method: 'POST',
headers: {
'X-API-Key': process.env.SONARSEND_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "jamie@example.com",
"reason": "string"
}),
});
const data = await res.json();{
"tenant_id": "9c21895d-57f0-4a15-a1df-4dc6835d4f80",
"email": "jamie@example.com",
"reason": "string",
"created_at": "2026-01-15T09:30:00.000Z"
}Un-suppress an address
Removes an address from the suppression list, lifting the send block. Requires suppression:write. The address goes in the query string, not the path, because it contains @ and dots — URL-encode it. Case is normalised here too.
Idempotent: removing an address that is not on the list is also a 204. Lifting a block does not resubscribe anyone — if the contact is unsubscribed they stay unsubscribed, which is separate state. Returns 204 with no body.
Address to un-suppress. URL-encode it; case is normalised.
The block was lifted (or the address was already absent).
The request failed validation, or a referenced record was rejected.
The tenant slug, or the record the path names, does not exist.
curl -X DELETE "https://api.sonarsend.com/t/acme/api/suppressions?email=" \ -H "X-API-Key: $SONARSEND_API_KEY"
const res = await fetch('https://api.sonarsend.com/t/acme/api/suppressions', {
method: 'DELETE',
headers: { 'X-API-Key': process.env.SONARSEND_API_KEY },
});
const data = await res.json();Suppress many contacts at once
Suppresses a selection of contacts by ID — the "act on this list of contacts" path behind the app's sunset-candidates flow. Requires suppression:write. Unlike the single-address endpoint, this takes contact IDs, and for each contact it both adds the address to the suppression list AND flips the contact to unsubscribed (if not already). Contacts with no email, or that do not exist, are skipped.
1–500 IDs per call; over 500 returns 400 TOO_MANY, so batch larger jobs client-side. reason defaults to "sunset" here (it is null when omitted on the single-address endpoint). Returns { suppressed }, the number actually acted on.
Contact UUIDs, 1–500 per call.
Audit note stored on each suppression. Defaults to sunset.
How many contacts were suppressed.
The request failed validation, or a referenced record was rejected.
The tenant slug, or the record the path names, does not exist.
curl -X POST "https://api.sonarsend.com/t/acme/api/suppressions/bulk" \
-H "X-API-Key: $SONARSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact_ids": [
"string"
],
"reason": "string"
}'const res = await fetch('https://api.sonarsend.com/t/acme/api/suppressions/bulk', {
method: 'POST',
headers: {
'X-API-Key': process.env.SONARSEND_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"contact_ids": [
"string"
],
"reason": "string"
}),
});
const data = await res.json();{
"suppressed": 0
}