Docs/Sending email

Suppressions

A suppression is an address Anypost will not deliver to. The list is your team's, and it protects your sending reputation by stopping mail to addresses that bounced, complained, or opted out.

How an address gets suppressed

Most suppressions are added automatically. You can also add one yourself.

reasonAdded when
permanent_bounceA receiving server permanently rejected delivery, usually a non-existent address.
complaintA recipient marked a message as spam.
unsubscribedA recipient used a one-click unsubscribe link.
manualYou added the address through the API or dashboard.

A complaint or a stream of bounces damages how mailbox providers see your domain. Suppressing those addresses on the first signal is what keeps the rest of your mail in the inbox.

Topic scope

Every suppression is scoped to a topic, and the scope decides which sends it blocks.

  • A global suppression has the topic *. It blocks every send to that address. Bounces and complaints always write a global suppression: a dead address is dead for all mail.
  • A topic-scoped suppression names one topic, such as marketing. It blocks only sends carrying that same topic. A one-click unsubscribe writes one of these, scoped to the topic the recipient unsubscribed from.

This scoping is the transactional carve-out. A recipient who unsubscribes from marketing is suppressed for marketing only, so a later password reset or one-time code, sent with a different topic or none at all, still reaches them. A send with no topic is checked against global suppressions only. See Tags, topics & campaigns.

What happens on a send to a suppressed address

When a send names an address that is suppressed for that send's topic, the address is dropped before delivery. The rest of the recipients are unaffected, and you are not billed for the dropped recipient. Anypost emits an email.suppressed event so the outcome is visible on your webhooks.

Listing suppressions

GET /v1/suppressions returns the list, newest first, with cursor pagination. The TypeScript list returns a page you can iterate to walk every page:

curl https://api.anypost.com/v1/suppressions \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Narrow the list with query parameters:

ParameterRestricts to
email_containsAddresses containing this substring.
topicOne topic. Pass * for global entries only.
reasonpermanent_bounce, complaint, unsubscribed, or manual.
originauto for automatic entries, manual for ones you added.

To check one address, GET /v1/suppressions/{email} returns every record on file for it, across all topics. The {email} segment is URL-encoded.

Adding a suppression

POST /v1/suppressions adds an address yourself, for example on a request from a customer:

curl https://api.anypost.com/v1/suppressions \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "topic": "marketing",
    "note": "customer requested removal"
  }'

topic is optional and defaults to *, a global suppression. Set a specific topic to block only that stream. note is an optional internal annotation. A manual suppression never expires. Adding an address that is already suppressed for the same (email, topic) pair returns 422.

Removing a suppression

Removing an address makes it eligible to receive mail again on the next send.

  • DELETE /v1/suppressions/{email} removes the address across every topic.
  • DELETE /v1/suppressions/{email}/{topic} removes one topic's entry and leaves the others. Use %2A for the global topic *.

Removal does not stop a fresh suppression later: a future bounce, complaint, or unsubscribe for that address writes a new record. Lift a suppression only when you have reason to believe the address is good again.

Expiry

A permanent_bounce suppression expires automatically after 90 days, on the chance the address is reassigned or the failure was temporary. complaint, unsubscribed, and manual suppressions do not expire. An expired entry is no longer enforced and no longer appears in the list.

Where to go next