PPactDocs
Administration

Suppressions

The tenant-scoped suppression list that blocks sends to bounced or complained addresses, auto-populated from provider webhooks and checked by the sequence engine before every send.

Suppressions

The suppression list is Pact's do-not-send registry. Any address on it is excluded from sends until you explicitly remove it. The list is tenant-scoped (email_suppressions table), auto-populated from email-provider webhooks, and consulted by the sequence engine before every send. Admin management lives at /v1/integrations/email-suppressions and requires admin or owner role.

How addresses get suppressed

Suppressions arrive two ways:

  • Automatically — the webhook handler in core/email/webhook_handler.py normalizes bounce and complaint events from Resend, SendGrid, Postmark, Mailgun, and SES into a common shape, then auto-suppresses on hard bounces and spam complaints. The originating event id is stored in source_event_id so you can trace a suppression back to the exact webhook.
  • Manually — an admin adds an address directly (reason defaults to manual).

Hard bounces vs. soft bounces

Only permanent failures auto-suppress. A hard bounce (invalid mailbox) or an abuse/spam complaint lands the address on the list; transient soft bounces are recorded as events but do not suppress, so a full inbox or a temporary outage does not permanently block a real contact.

List and filter

code
GET /v1/integrations/email-suppressions?reason=hard_bounce&limit=100

Returns active suppressions (where unsuppressed_at IS NULL), newest first, optionally filtered by reason. Each row includes the email, reason, source_event_id, and suppressed_at.

Add manually

code
POST /v1/integrations/email-suppressions
{ "email": "[email protected]", "reason": "manual" }

Adds (or re-suppresses) an address. The insert is idempotent — re-adding a previously unsuppressed address clears its unsuppressed_at and refreshes the timestamp. An email.suppression.added audit event is written.

Remove (unsuppress)

code
DELETE /v1/integrations/email-suppressions/{suppression_id}

This is a soft removal — it stamps unsuppressed_at rather than deleting the row, preserving history. An email.suppression.removed audit event captures the address.

Unsuppress deliberately

Removing a hard-bounced or complained address puts it back in your sendable pool. If it bounces or complains again, your sender reputation takes a second hit — and the webhook will simply re-suppress it. Only unsuppress addresses you have a concrete reason to believe are now valid.

Batch check (used by the sequence engine)

code
POST /v1/integrations/email-suppressions/check
{ "emails": ["[email protected]", "[email protected]"] }

Returns two arrays — suppressed and deliverable. The sequence engine calls this before a send to split a batch into addresses it may mail and addresses it must skip. This endpoint requires authentication but not the admin role, because it is a read-only pre-send check rather than an administrative mutation.