message.comDevelopers

Suppressions Live

The suppression list is the workspace's do-not-send roster. Addresses on this list will not receive outbound email, regardless of the source. Hard bounces are added automatically; complaints from feedback loops are added automatically; agents can add or remove entries manually.

Reasons

ReasonSourceBehaviour
hard_bounceOutbound webhookAdded immediately on permanent bounce.
soft_bounce_exceededOutbound webhookAdded after three transient failures.
complaintOutbound webhook (feedback loop)Added immediately on spam complaint.
manualAgent or APIExplicit add (e.g., customer asked to be removed).

List suppressions

GET/api/v1/suppressionsAuth: Bearer

Cursor-paginated. Filters: reason, email (prefix match).

Code samples

cURL
curl 'https://app.message.com/api/v1/suppressions' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/suppressions', {
  headers: { Authorization: 'Bearer ' + token }
});
const { suppressions } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/suppressions",
    headers={"Authorization": f"Bearer {token}"},
)
suppressions = r.json()["suppressions"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/suppressions")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer #{token}"
  http.request(req)
end
suppressions = JSON.parse(res.body)["suppressions"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$suppressions = json_decode(file_get_contents("https://app.message.com/api/v1/suppressions", false, $ctx), true)["suppressions"];

Add to suppressions

POST/api/v1/suppressionsAuth: Bearer

Adds an email to the list. If the email is already suppressed with the same reason, returns the existing record (idempotent). Note text is optional and admin-visible only.

FieldTypeDescription
emailrequiredstringAddress to suppress. Normalised to lowercase.
reasonoptionalenumOne of the four reasons. Defaults to manual.
noteoptionalstringFree-form note. Audit trail only.
Body
{
  "email": "[email protected]",
  "reason": "manual",
  "note": "Customer asked to be removed via phone"
}
200 OK
{
  "id": "uuid",
  "email": "[email protected]",
  "reason": "hard_bounce",
  "note": "550-5.1.1 The email account that you tried to reach does not exist",
  "createdAt": "2026-05-13T15:30:00Z"
}

Remove from suppressions

DELETE/api/v1/suppressions/:idAuth: Bearer

Removes an entry. The address is eligible to receive outbound mail again on the next attempt. Use sparingly: a removed entry that immediately re-bounces hurts your sender reputation.

Removing a complaint entry is risky. Spam complaints come from the recipient explicitly marking your message as spam. Re-mailing them often triggers further complaints and an ESP-side block.

Outbound behaviour with suppressions

When you send via /tickets/:id/reply or /conversations/:id/messages and the visitor email is on the suppression list:

  • If sendEmail is the default (true for tickets, false for chat): the message is recorded with deliveryStatus: "suppressed" and not delivered.
  • The API returns 200, not an error. We surface the suppression status in the response body.
  • The dashboard shows a red banner on the conversation explaining why the message did not go out.

Errors

CodeWhen
400 invalid_bodyEmail format is not valid.
403 forbiddenAgent role does not allow suppression edits.
404 not_foundSuppression record not found in this workspace.

Common pitfalls

  • Importing a suppression list from another vendor. Bulk import is admin-only and rate-limited. POST one at a time or contact us for a bulk-load.
  • Confusing suppression with deletion. Suppressing an email does not delete the visitor record or their conversation history. It only blocks future outbound mail.
  • Manually adding a customer who replied "stop". Add them with reason: manual and a note. Auto-removal does not happen.