EmailmoversMyDataHub docs
Browse the docs

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.

Updated 4 October 2026View as Markdown

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]"]
}
kindWhat the values areHow they are read
emailEmail addressesTrimmed, lower cased and hashed
domainDomainsTrimmed, lower cased and hashed. *.acme.co.uk is a suffix match, and a wildcard needs a domain, not *.com
phoneTelephone numbersRead as E.164 digits: 0113 234 5671 becomes 441132345671
company_numberCompanies House numbersUpper case and padded to 8 characters: 5046417 becomes 05046417
title_termWords in a job titleKept 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_statusMeaning
noneNot suppressed
objected_to_emailmoversThe person objected to Emailmovers, so the record is suppressed database-wide
objected_to_licenseeThe person objected to an organisation that holds the record, and it is on that organisation's objections list
deceasedThe person has died
left_companyThe 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."
}
scopeEffect
licenseeSuppresses the record for your organisation at once. The response is 201 with status suppressed
emailmoversSuppresses 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.

  1. 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.
  2. An organisation may report 200 a day. Beyond that the answer is a 429 with the same advice.
  3. 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