Import suppression lists before migrating email providers

Published on June 02, 2026

Why bounces, complaints, unsubscribes, and manual blocks should move before your first send through a new email provider.

The risky part of an email provider migration is not usually the send API. You can wrap a new endpoint, test a staging message, and ship a credentials swap in a day.

The risky part is state.

Your old provider knows who hard-bounced, who complained, who unsubscribed, and which recipients your team blocked manually. Your new provider does not know any of that until you import it.

If you skip this step, the first production send through the new provider can contact recipients who were already suppressed in the old system.

What suppression lists protect

A suppression list protects three things at once:

  1. Recipient expectations.
  2. Sender reputation.
  3. Your own support and compliance posture.

Hard bounces tell you an address should not receive more mail. Spam complaints tell you a recipient or mailbox provider considered the message unwanted. Unsubscribes are a direct request to stop a class of mail.

Those are not just dashboard counters. They are operational rules that must survive a provider migration.

Import before the first real send

The safest order is:

  1. Add and verify the new provider's DNS records.
  2. Configure webhooks.
  3. Export suppressions from the old provider.
  4. Import suppressions into the new provider.
  5. Send staging and low-risk production traffic.
  6. Ramp gradually.

Importing after cutover is too late. By then, the new provider may already have sent to addresses that should have been blocked.

What to export

Export suppression data by reason whenever the provider supports it.

ProviderExport
SendGridBounces, spam reports, global unsubscribes, group unsubscribes, blocks or invalids
MailgunBounces, complaints, unsubscribes
PostmarkSuppression dump per message stream
ResendSuppression list rows for hard bounces and spam complaints
Amazon SESAccount-level suppressed destinations

Do not treat soft bounces as suppressions by default. A soft bounce is a temporary delivery failure. Keep it in your historical analytics, but do not turn it into a permanent block unless your old provider explicitly promoted it to a hard bounce or manual suppression.

Preview first, then commit

Postscale's suppression import flow is deliberately two-step.

In the dashboard, open /dashboard/suppressions, choose a provider under Import Suppressions, upload the CSV, and click Preview. The preview shows valid rows, invalid rows, and duplicates before anything is written.

The API import flow also expects CSV text. If the old provider gives you a JSON array, convert it to CSV first. Do not post hard-bounce or complaint rows one by one to POST /v1/suppressions; that direct endpoint is only for manual blocks and scoped unsubscribes.

Through the API, create a preview:

curl -X POST https://api.postscale.io/v1/imports/suppressions/preview \
  -H "Authorization: Bearer ps_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "mailgun",
    "source_filename": "mailgun-complaints.csv",
    "default_reason": "complaint",
    "content": "email,reason\nabuse@example.com,complaint\n"
  }'

Then commit the previewed job:

curl -X POST https://api.postscale.io/v1/imports/suppressions/jobs/IMPORT_JOB_ID/commit \
  -H "Authorization: Bearer ps_live_your_api_key"

Committed rows are idempotent. Existing suppressions are skipped, not duplicated, and new rows are tagged with source values such as import:mailgun or import:sendgrid.

Keep reason data

The worst CSV export is one that only says:

email
user@example.com

That can still be useful, but it forces you to choose a default reason for every row. A better export keeps the provider's reason:

email,reason
user@example.com,hard_bounce
spam@example.com,complaint
old@example.com,unsubscribe

Reason data matters later. Support can tell whether a recipient bounced, complained, or opted out. Deliverability review can separate list hygiene from abuse signals. Compliance review can distinguish a normal unsubscribe from a manual block.

Scoped unsubscribes

Hard bounces and complaints should stay org-wide. If a mailbox permanently rejects mail or reports abuse, do not keep sending from another stream.

Unsubscribes are more nuanced. A recipient may unsubscribe from product updates but still need password resets, invoices, and security notices.

Postscale supports scoped unsubscribes with scope_type and scope_id:

email,reason,scope_type,scope_id
user@example.com,unsubscribe,list,product-updates

Use scoped imports only when the old provider export carries reliable stream, list, template, or domain context. If you are unsure, import unsubscribes org-wide. It is blunt, but safer.

Re-export the delta

Keep the old provider active for a short overlap period. Even after traffic moves, delayed bounces and webhook retries can arrive there.

After the final cutover, export suppressions one more time and import the delta into Postscale. The import is idempotent, so already-imported rows are skipped.

That final pass closes the gap between "we stopped sending through the old provider" and "the old provider has no more useful state."

For the full operational checklist, use the Suppression List Migration Guide. For API details, see the Suppressions API.