Suppression and opt-outs

The suppression list is your do-not-contact register. Any identifier on it (a phone number or email address) is silently skipped at send time — for both single sends and campaigns — so you never message someone who has opted out.

Why it matters (POPIA)

South Africa's POPIA requires that you honour opt-outs and stop contacting people who have withdrawn consent. Suppression makes that the default: once an identifier is suppressed, Blueticked enforces it on every send across the workspace, so compliance does not depend on each integration remembering to check.

STOP auto-suppresses

When a customer replies STOP (or another recognised opt-out keyword) on WhatsApp or SMS, Blueticked adds them to the suppression list automatically with a reason of stop_keyword. Hard bounces and spam complaints on email suppress automatically too (bounce / complaint). You do not need to wire any of this up — it happens server-side.

List entries

Cursor-paginated, newest first. Optionally filter by channel:

list.ts
const page = await bt.suppression.list({ limit: 100 });

for (const entry of page.data) {
  // entry.identifier, entry.channel, entry.reason, entry.created_at
  console.log(entry.identifier, entry.reason);
}

// Only email opt-outs:
const emailOptOuts = await bt.suppression.list({ channel: "email" });

Add an opt-out

Add an entry yourself when someone opts out through your own channels (a CRM, a call centre, an unsubscribe form). Use channel: "all" to block every channel, or a specific channel to opt out of just that one. It is idempotent — re-adding the same identifier returns the existing entry:

add.ts
const entry = await bt.suppression.add({
  identifier: "+27821234567",
  channel: "all",
  reason: "manual",
  reason_detail: "Opted out via CRM",
});

console.log(entry.id); // "sup_123"

Valid reason values are manual, stop_keyword, bounce, and complaint; for your own additions use manual.

Remove an entry

Removing an entry makes that identifier contactable again — only do this when you have genuine, recorded consent to resume contact:

remove.ts
await bt.suppression.remove("sup_123");

Suppression vs. the contact gate

The suppression list is keyed by identifier (a phone or email), so it applies even before a contact exists. A contact also has its own suppressed flag (see Contacts) that blocks every channel for that one contact record. Both are checked at send time; either one being set is enough to skip the send.