REST API
Suppressions
Exclude an email address or a whole domain from every campaign in the workspace, and list what is excluded, from your CRM, your unsubscribe page or a Zap.
Updated 4 September 2026
The suppression list is the memory of who must never receive an email from this workspace. The one-click unsubscribe link writes to it; so can you.
POST /api/v1/suppressions
curl -X POST https://app.seegnals.com/api/v1/suppressions \
-H "Authorization: Bearer $SEEGNALS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "target": "jane@example.com" }'
const res = await fetch("https://app.seegnals.com/api/v1/suppressions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SEEGNALS_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"target": "jane@example.com"
})
});
const json = await res.json().catch(() => null);
console.log(res.status, json);
import os, requests
res = requests.post(
"https://app.seegnals.com/api/v1/suppressions",
headers={"Authorization": f"Bearer {os.environ['SEEGNALS_TOKEN']}"}, json={
"target": "jane@example.com"
},
timeout=20,
)
print(res.status_code, res.json() if res.content else None)
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
target |
string | yes | An email address, or a domain such as acme.com. Trimmed and lower-cased. An address must pass the same check as a prospect email. A domain needs at least two labels and no scheme, path or @. |
Body limit 4 KiB.
Response 201
{ "id": "c0a8012e-9d4f-4d3e-9a1e-6a1d2f3b4c5d", "kind": "email", "value": "jane@example.com" }
kind is email or domain; value is the normalised target. The entry is stored with the reason Excluded via the API. and appears in Settings → Suppressions like any other.
Effect
The sending engine reads the suppression list on every send attempt, without caching. The exclusion applies from the next attempt, including to people already enrolled in a running campaign. A domain entry blocks every address at that domain, present and future.
Errors
| Status | Body |
|---|---|
400 |
{ "error": "`target` must be a non-empty string — an email address or a domain." } |
400 |
{ "error": "`target` is not a valid email address or domain (e.g. acme.com)." } |
409 |
{ "error": "jane@example.com is already excluded.", "code": "duplicate", "kind": "email", "value": "jane@example.com" } |
500 |
{ "error": "Couldn't exclude it: …" } |
A 409 means the address was already excluded, which is what you wanted. Treat it as success.
GET /api/v1/suppressions
Query: kind (email or domain), limit and cursor.
{ "data": [ { "id": "…", "kind": "email", "value": "jane@example.com", "reason": "Excluded via the API.", "created_at": "2026-09-03T00:00:00.000+00:00" } ], "next_cursor": null }
Only the workspace list is returned. The global suppression list that Seegnals also applies at send time is not visible here.
DELETE /api/v1/suppressions/{id}
Removes one workspace entry, the same as Remove in Settings → Suppressions. 204 with no body. The address becomes contactable from the next send attempt; enrollments that were stopped earlier because of the suppression are not revived, exactly as in the app.
404 { "error": "Suppression not found." } for an unknown id, another workspace’s id, a non-UUID, and for entries of the global Seegnals list, which the workspace API does not touch.