Guide
Suppressions and objections
Upload suppression lists that apply to every count and order, check records before a send, and report an objection so it reaches every licensee holding the record.
Suppression runs both ways. You upload your own lists, and an objection reported by anyone reaches every organisation that holds the record.
Lists are free, apply to every later count and order, and are stored as SHA-256 hashes only. Everyone has an absolute right to object to direct marketing, and it is kept by suppression, not erasure.
Upload a list
POST /v1/suppressions takes a name, a kind and up to 100,000 values.
{
"name": "Existing customers",
"kind": "email",
"values": ["[email protected]", "[email protected]"]
}kind | What the values are | How they are read |
|---|---|---|
email | Email addresses | Trimmed, lower cased and hashed |
domain | Domains | Trimmed, lower cased and hashed. *.acme.co.uk is a suffix match, and a wildcard needs a domain, not *.com |
phone | Telephone numbers | Read as E.164 digits: 0113 234 5671 becomes 441132345671 |
company_number | Companies House numbers | Upper case and padded to 8 characters: 5046417 becomes 05046417 |
title_term | Words in a job title | Kept as words, at most five, never hashed |
The normalisation follows the advertising platform convention, so an existing suppression file works unchanged. If you already hold SHA-256 hashes, send hashed true with 64 lower case hex characters per value.
The response tells you what it read. A repeated value is skipped, the first 100 skipped rows are named with a reason, and rows_read less rows_valid counts them all. A list with nothing valid is a 422.
{
"list": { "id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA", "name": "Existing customers", "kind": "email", "row_count": 1198 },
"rows_read": 1204,
"rows_valid": 1198,
"rows_skipped": [{ "row": 17, "reason": "Not an email address." }]
}A suppression list is processed under the Article 28 data processing agreement, so your organisation accepts it before the first upload. A person who owns the account accepts it in the app's Settings, or with POST /v1/account/agreements and {"dpa_accepted_version": "1.0"}, the version GET /v1/account names in agreements.dpa. The app's first upload asks with a box of its own.
Until it is accepted, an upload answers 403 dpa-acceptance-required and nothing is uploaded. When a new version is in force, it is accepted again.
Use a list in an audience
Name the list in an in_list filter, usually under not.
{ "not": { "field": "email.address_sha256", "op": "in_list", "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA" } }Each count reports what each list removed in compliance_summary.suppressed_removed, as {list_id, removed}. Title term and domain wildcard lists report the same way.
Suppressed records never appear in counts or orders, and a matched record is never charged. See The audience definition.
Check before you send
POST /v1/suppressions/check takes up to 1,000 record_ids and returns the status of each as of now. Run it before any send.
{ "record_ids": ["contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"] }suppression_status | Meaning |
|---|---|
none | Not suppressed |
objected_to_emailmovers | The person objected to Emailmovers, so the record is suppressed database-wide |
objected_to_licensee | The person objected to an organisation that holds the record, and it is on that organisation's objections list |
deceased | The person has died |
left_company | The person has left the company |
Each result also says suppressed and which of your list_ids hold the record. A record the current dataset no longer holds is still found if it was objected to.
Report an objection
POST /v1/objections, or report_objection over MCP, records an objection to direct marketing. Send exactly one of record_id or email_sha256, with the channel it arrived by, when it was received_at and a scope.
{
"record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
"channel": "email",
"received_at": "2026-10-01T08:30:00Z",
"scope": "emailmovers",
"note": "Replied asking not to be contacted again."
}scope | Effect |
|---|---|
licensee | Suppresses the record for your organisation at once. The response is 201 with status suppressed |
emailmovers | Suppresses it database-wide. The response is 201 with status pending and an effective_by time of 17:00 UTC on the next working day |
The record goes on your objections list immediately for both scopes. A database-wide objection then reaches every licensee through a same-day overlay that is subtracted from every count, sample and order, and each organisation holding the record gets a signed suppression.created webhook.
The webhook carries the record, the reason, the scope and the time. It never says who reported it or what the note said.
Because a licensee must not be able to remove records from every other customer's counts unchecked, scope emailmovers has three conditions.
- You must hold the record, from a delivered live order or an enrichment. Otherwise it is a 422 that advises scope
licensee, which still protects the person for your organisation at once. - An organisation may report 200 a day. Beyond that the answer is a 429 with the same advice.
- It costs one unit of your counts budget. See Rate limits.
Pull instead of waiting
GET /v1/suppressions?since= returns the lists changed after a time, each with added_since, the notices for records added to it. Use it to catch up after downtime, alongside the suppression.created webhook.
What a delivered record looks like after an objection
A record objected to after delivery stays in your records pages and downloads, so counts, cursors and your CRM's own key still line up. Its email, telephone number and name are blank, and compliance.suppression_status says why.
A file downloaded after that no longer hashes to the content_sha256 on the receipt, which records the day of delivery. See Compliance receipts.
Deadlines and law
The right to object to direct marketing is absolute under UK GDPR, and an objection must be honoured within one month. Here it takes effect for your organisation at once, and database-wide within one working day. Telephone screening is separate: every telephone number is screened against the TPS and CTPS each night through a licensed screening service, and carries its status and the date of that screen, valid for 28 days.
Next steps
- Check the objection and list endpoints in the REST reference.
- Read how receipts count suppressed records in Compliance receipts.
- Subscribe to
suppression.createdin Webhooks.