Move from SendGrid to Postscale

Update sending calls, SMTP settings, inbound routes, templates, suppressions, and webhooks using the mappings below.

  • Replace SendGrid Mail Send with POST /v1/send.
  • Map categories and custom_args to Postscale tags and metadata.
  • Replace Inbound Parse with structured inbound email webhooks.
  • Keep API and SMTP cutover paths available for rollback.

What changes when you move.

A direct map from SendGrid concepts to the Postscale API and operational model.

SendGridPostscaleMigration note
Mail Send APIPOST /v1/sendNormalize personalizations into to, cc, bcc arrays and move custom_args into metadata.
Event WebhookPostscale webhooksSubscribe to received, delivered, bounced, deferred, and complained events per endpoint.
Inbound ParseInbound Email APIPoint MX at Postscale and receive parsed JSON with headers, body, and attachments.
Dynamic TemplatesPostscale templatesImport HTML and Handlebars variables, then send by template slug or ID.
SuppressionsSuppression APIExport bounces, spam reports, unsubscribes, blocks, and invalids separately, then preview the CSV before commit.

Move your integration step by step

01

Add Postscale DNS records

Add Postscale verification, DKIM, return-path, and optional MX records while the old provider keeps sending.

02

Update your integration

Swap API credentials and normalize the send payload. Keep the old provider path behind a feature flag for rollback.

03

Import suppressions and templates

Preview and import suppression exports, move template HTML, then configure delivery, bounce, complaint, and inbound webhooks.

04

Move traffic gradually

Start at 10 percent, watch bounces and complaints by ISP, then increase volume as warming limits allow.

Convert the send call.

Compare the existing send request with its Postscale equivalent.

SendGrid
import sgMail from "@sendgrid/mail";

sgMail.setApiKey(process.env.SENDGRID_API_KEY);

await sgMail.send({
  from: "Acme <alerts@example.com>",
  to: "user@example.com",
  subject: "Welcome",
  html: "<p>Hello from Acme</p>",
  categories: ["onboarding"],
  customArgs: { user_id: "usr_123" },
});
Postscale
await fetch("https://api.postscale.io/v1/send", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.POSTSCALE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    from: "Acme <alerts@example.com>",
    to: ["user@example.com"],
    subject: "Welcome",
    html_body: "<p>Hello from Acme</p>",
    tags: ["onboarding"],
    metadata: { user_id: "usr_123" },
  }),
});

Production checklist.

Lower DNS TTL to 300 seconds at least 24 hours before cutover.
Keep both DKIM selectors published during the transition.
Import hard bounces, complaints, unsubscribes, and manual suppressions through /dashboard/suppressions before the first production send.
Handle both providers’ webhook formats until events from the old provider have finished arriving.
Send seed tests to Gmail, Outlook, Yahoo, iCloud, and a corporate Microsoft 365 tenant.
Cut over early in the week and avoid final traffic moves on Friday.
Monitor delivery, bounce, deferred, and complaint rates by ISP after each traffic increase.
Keep the old account active until delayed events and user replies have stopped arriving.

FAQ

Can SendGrid and Postscale run at the same time?

Yes. Publish both DKIM selectors, keep SendGrid active, and split traffic in your application until Postscale delivery metrics are stable.

What replaces SendGrid Inbound Parse?

Postscale inbound email webhooks receive parsed message metadata, bodies, headers, and attachments after you point MX records at Postscale.

Do I need to rewrite all templates?

No. Keep rendering HTML in your app or import template HTML and variables into Postscale templates.

How do I move SendGrid suppressions?

Export bounces, spam reports, global unsubscribes, group unsubscribes, blocks, and invalids, then preview and commit them in /dashboard/suppressions before sending through Postscale.

Start your migration to Postscale.