Skip to Content
Suppressions

Suppressions

A suppression is an account-wide “never email this address” entry. One entry blocks the address in every audience and on transactional sends. It outranks a contact’s status, a campaign’s targeting, and a POST /emails.

Moving from another provider? Import its suppression list before your first send. Otherwise your first campaign re-mails every address that already bounced or complained elsewhere, and receiving providers notice.

The Suppression object

{ "id": "sup_9x4v0dz1k2m7", "object": "suppression", "email": "bounced@example.com", "reason": "bounced", "source": "api:key_2v0dz1k9x4m", "created_at": "2026-08-10T12:00:00.000Z" }
reasonMeaningWritable over the API
unsubscribedOpted out.Yes
bouncedHard bounce.Yes
complainedMarked as spam.Yes
manualAdded by hand in the app.No
provider_suppressedSuppressed by the mail provider.No

source is app for the UI or api:<key id> for an API write, so a bad import can be traced to its key.

List suppressions

GET/v1/suppressions

Your account’s own entries, newest first, cursor-paginated.

curl "https://go.day3.app/api/v1/suppressions?limit=100" \ -H "Authorization: Bearer $DAY3_API_KEY"

Check one address

GET/v1/suppressions/{email}

200 with the entry if suppressed, 404 if not. URL-encode the email. Use it to find out why a batch item failed with email_suppressed.

curl https://go.day3.app/api/v1/suppressions/bounced%40example.com \ -H "Authorization: Bearer $DAY3_API_KEY"

This check also consults day3’s global suppression entries, so it can return 200 for an address that is not in your list.

Add suppressions

POST/v1/suppressions
FieldTypeRequiredNotes
reasonstringYesunsubscribed, bounced or complained. No default, so every entry is attributable.
emailsstring[]YesUp to 1,000 per call.
curl -X POST https://go.day3.app/api/v1/suppressions \ -H "Authorization: Bearer $DAY3_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: suppression-import-1" \ -d '{ "reason": "bounced", "emails": ["a@x.com", "b@y.com"] }'

The response shows the blast radius:

{ "added": 950, "already_suppressed": 45, "invalid": 5, "total_suppressed_before": 200, "total_suppressed_after": 1150 }

The API’s biggest foot-gun. Post a full contact export instead of a suppression export and your whole audience becomes unmailable, silently. Check total_suppressed_after against what you expected.

Idempotency-Key is supported. Set it on imports.

There is no delete

API writes are add-only. There is no DELETE /v1/suppressions/{email}.

Un-suppress in the app, per address, under Audiences then Suppressions, with reason and source visible. A scripting mistake stays recoverable but cannot be bulk-reverted by script, and a leaked key cannot un-suppress bounced addresses to force-mail them.

Un-suppressing restores contacts marked bounced, complained or suppressed to subscribed. Self-service unsubscribes stay unsubscribed.

Interaction with contacts

Suppressing an address does not delete contact rows; they become unmailable. Creating a contact for a suppressed address returns 409 email_suppressed.

Import suppressions before contacts, and expect those rows to fail on the way in. That is correct, not something to retry. See Migrate a list.

Interaction with transactional email

  • An unsubscribe does not block a transactional send. A newsletter opt-out must never stop a password reset.
  • A bounce, complaint or provider suppression does, with 400 email_suppressed.

See Emails.

Last updated on