ChangelogStatus
Docs/API reference

Suppressions API

Manage the per-team suppression list — addresses blocked from future sends.

Every request needs a bearer token and goes to a path under https://api.anypost.com/v1. See API conventions for the shared request, error, and pagination rules.

List suppressions

GET /v1/suppressions

Returns the authenticated team's suppression list, newest-first, with cursor pagination. Includes addresses suppressed automatically from permanent bounces and complaints as well as manual entries. Rows whose expires_at has passed are filtered out automatically — they aren't enforced on send and don't appear here.

Parameters

limitintegerin query[optional]

Number of items to return.

afterstringin query[optional]

Opaque cursor from a previous response's next_cursor. Do not parse.

email_containsstringin query[optional]

Case-insensitive substring match against the suppressed address.

topicstringin query[optional]

Restrict to entries scoped to this topic. Pass * to see only global (bounce/complaint/manual) suppressions, or a specific topic name (e.g. marketing) to see only topic-scoped unsubscribes. Omit to see every topic.

reasonstringin query[optional]

Restrict to entries with this reason.

One of: permanent_bounce, complaint, unsubscribed, manual.

originstringin query[optional]

Restrict to entries added by this origin.

One of: auto, manual.

Example request

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

Response body

On success (200), the response body is:

dataarray of Suppression
has_moreboolean
next_cursorstring

May be null.

{
  "data": [
    {
      "id": "sup_550e8400-e29b-41d4-a716-446655440000",
      "email": "[email protected]",
      "topic": "*",
      "reason": "permanent_bounce",
      "origin": "auto",
      "classification": "string",
      "smtp_code": 0,
      "note": "string",
      "suppressed_at": "string",
      "expires_at": "string",
      "created_at": "string"
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Responses

StatusDescription
200Paginated list of suppressions.
401Missing or invalid credentials.

Add a manual suppression

POST /v1/suppressions

Suppresses a single recipient address for the authenticated team. The email is normalized (trimmed + lowercased) before storage and uniqueness check, so [email protected] and [email protected] collide. Manual entries never expire; use DELETE /suppressions/{email}/{topic} to remove one.

A 422 validation_error is returned if an active suppression for the same normalized (email, topic) pair already exists for the team. To remove an entry, call DELETE /suppressions/{email}/{topic} with the customer-supplied address (and optional topic) as path parameters.

Request body

Send as JSON with Content-Type: application/json.

emailstring (email)[required]
topicstring[optional]

Optional topic to scope the suppression. Omit (or send *) to block every topic for this address. Send a specific topic (e.g. marketing) to leave other topics — typically transactional traffic — unaffected.

notestring[optional]

Optional internal annotation (e.g. "customer requested removal"). Preserved if an automatic bounce later re-suppresses this address.

May be null.

Example request

curl https://api.anypost.com/v1/suppressions \
  -X POST \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]"
  }'

Response body

On success (201), the response body is:

idstring

Stable identifier for log correlation. Lookups and deletes are keyed on (email, topic), not on this id.

emailstring (email)

The suppressed recipient address, normalized to lowercase with surrounding whitespace trimmed. Together with topic, forms the natural key for GET / DELETE /suppressions/{email}/{topic}.

topicstring

The topic this suppression is scoped to. The wildcard * means "every topic" — bounces and complaints always write * so the address is suppressed for all sends. A specific topic (e.g. marketing) only blocks sends tagged with that same topic, leaving transactional traffic (otp, password-reset, …) unaffected. Topics are lowercased on write.

reasonstring

Why the address is suppressed.

  • permanent_bounce — the receiving server reported a permanent delivery failure (e.g. InvalidRecipient, BadDomain). Always topic *.
  • complaint — an ARF feedback report (FBL) classified as abuse, fraud, virus, or opt-out. Always topic *.
  • unsubscribed — the recipient one-click unsubscribed (RFC 8058 POST to /u/{token}). Scoped to the topic from the unsubscribe token.
  • manual — added through the API/UI or via CSV import. Topic-scoped or *.

One of: permanent_bounce, complaint, unsubscribed, manual.

originstring

Provenance of the row.

  • auto — written automatically from a bounce or complaint event.
  • manual — created through this API or the dashboard.

One of: auto, manual.

classificationstring

For permanent_bounce, the bounce classification (e.g. InvalidRecipient). For complaint, the ARF feedback-type (abuse, fraud, …). Null for manual entries.

May be null.

smtp_codeinteger

The SMTP reply code on the bounce that produced this suppression. Null for complaints and manual entries.

May be null.

notestring

Free-form note attached at creation. Preserved across automatic re-suppressions of the same address.

May be null.

suppressed_atstring (date-time)

When the suppression was first observed (bounce / complaint timestamp for auto, creation time for manual).

expires_atstring (date-time)

When this suppression stops applying. Null means it never expires (complaints and manual entries by default). Permanent bounces expire on a rolling 90-day window.

May be null.

created_atstring (date-time)
{
  "id": "sup_550e8400-e29b-41d4-a716-446655440000",
  "email": "[email protected]",
  "topic": "*",
  "reason": "permanent_bounce",
  "origin": "auto",
  "classification": "string",
  "smtp_code": 0,
  "note": "string",
  "suppressed_at": "string",
  "expires_at": "string",
  "created_at": "string"
}

Responses

StatusDescription
201Suppression created.
401Missing or invalid credentials.
422Request validation failed.

List every suppression for an email

GET /v1/suppressions/{email}

Returns every suppression record on file for the recipient address, across all topics. Since a single address can be suppressed globally (*) and/or scoped to specific topics (e.g. marketing), this endpoint returns the full set. The {email} path segment is URL-encoded and matched case-insensitively after trim + lowercase, so Alice%40Example.com and alice%40example.com resolve to the same rows. Returns 404 if no active suppressions exist for this address on the authenticated team.

To target a single (email, topic) pair, use GET /suppressions/{email}/{topic} instead.

Parameters

emailstringin path[required]

URL-encoded recipient email address.

Example request

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

Response body

On success (200), the response body is:

dataarray of Suppression
{
  "data": [
    {
      "id": "sup_550e8400-e29b-41d4-a716-446655440000",
      "email": "[email protected]",
      "topic": "*",
      "reason": "permanent_bounce",
      "origin": "auto",
      "classification": "string",
      "smtp_code": 0,
      "note": "string",
      "suppressed_at": "string",
      "expires_at": "string",
      "created_at": "string"
    }
  ]
}

Responses

StatusDescription
200All suppressions for this address.
404Resource not found.

Remove every suppression for an email

DELETE /v1/suppressions/{email}

Removes the address from the suppression list across every topic. After this call the address is immediately eligible to receive mail again on the next send (regardless of topic). An automatic bounce or complaint event afterwards will create a fresh global (*) row; a future one-click unsubscribe will create a fresh topic-scoped row.

To remove only one topic's row, use DELETE /suppressions/{email}/{topic} instead.

Parameters

emailstringin path[required]

URL-encoded recipient email address.

Example request

curl https://api.anypost.com/v1/suppressions/alice%40example.com \
  -X DELETE \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Responses

StatusDescription
204Deleted.
404Resource not found.

Retrieve a suppression by email and topic

GET /v1/suppressions/{email}/{topic}

Returns the single suppression record for the (email, topic) pair, or 404 if it isn't suppressed for the authenticated team. Use * as the topic to fetch the global row written by bounces, complaints, and global manual entries.

Parameters

emailstringin path[required]

URL-encoded recipient email address.

topicstringin path[required]

Topic the suppression is scoped to. * resolves the global row; any other value resolves a topic-scoped unsubscribe / manual entry. URL-encode * as %2A if your HTTP client does not allow literal asterisks in path segments.

Example request

curl https://api.anypost.com/v1/suppressions/alice%40example.com/marketing \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

idstring

Stable identifier for log correlation. Lookups and deletes are keyed on (email, topic), not on this id.

emailstring (email)

The suppressed recipient address, normalized to lowercase with surrounding whitespace trimmed. Together with topic, forms the natural key for GET / DELETE /suppressions/{email}/{topic}.

topicstring

The topic this suppression is scoped to. The wildcard * means "every topic" — bounces and complaints always write * so the address is suppressed for all sends. A specific topic (e.g. marketing) only blocks sends tagged with that same topic, leaving transactional traffic (otp, password-reset, …) unaffected. Topics are lowercased on write.

reasonstring

Why the address is suppressed.

  • permanent_bounce — the receiving server reported a permanent delivery failure (e.g. InvalidRecipient, BadDomain). Always topic *.
  • complaint — an ARF feedback report (FBL) classified as abuse, fraud, virus, or opt-out. Always topic *.
  • unsubscribed — the recipient one-click unsubscribed (RFC 8058 POST to /u/{token}). Scoped to the topic from the unsubscribe token.
  • manual — added through the API/UI or via CSV import. Topic-scoped or *.

One of: permanent_bounce, complaint, unsubscribed, manual.

originstring

Provenance of the row.

  • auto — written automatically from a bounce or complaint event.
  • manual — created through this API or the dashboard.

One of: auto, manual.

classificationstring

For permanent_bounce, the bounce classification (e.g. InvalidRecipient). For complaint, the ARF feedback-type (abuse, fraud, …). Null for manual entries.

May be null.

smtp_codeinteger

The SMTP reply code on the bounce that produced this suppression. Null for complaints and manual entries.

May be null.

notestring

Free-form note attached at creation. Preserved across automatic re-suppressions of the same address.

May be null.

suppressed_atstring (date-time)

When the suppression was first observed (bounce / complaint timestamp for auto, creation time for manual).

expires_atstring (date-time)

When this suppression stops applying. Null means it never expires (complaints and manual entries by default). Permanent bounces expire on a rolling 90-day window.

May be null.

created_atstring (date-time)
{
  "id": "sup_550e8400-e29b-41d4-a716-446655440000",
  "email": "[email protected]",
  "topic": "*",
  "reason": "permanent_bounce",
  "origin": "auto",
  "classification": "string",
  "smtp_code": 0,
  "note": "string",
  "suppressed_at": "string",
  "expires_at": "string",
  "created_at": "string"
}

Responses

StatusDescription
200The suppression.
404Resource not found.

Remove a suppression by email and topic

DELETE /v1/suppressions/{email}/{topic}

Removes the single (email, topic) row from the suppression list. Other topics for the same address are untouched. After this call sends tagged with this topic are again eligible for delivery.

Parameters

emailstringin path[required]

URL-encoded recipient email address.

topicstringin path[required]

Example request

curl https://api.anypost.com/v1/suppressions/alice%40example.com/marketing \
  -X DELETE \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Responses

StatusDescription
204Deleted.
404Resource not found.