Move from Postmark to Postscale

Update API calls or SMTP settings, move templates and suppressions, and map inbound and delivery webhooks.

  • Convert PascalCase API fields into Postscale snake_case JSON.
  • Record stream names in tags or metadata, and review routing and isolation requirements separately.
  • Keep server API token changes isolated behind one mail adapter.
  • Move templates by alias and keep HTML rendering in your app if preferred.

What changes when you move.

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

PostmarkPostscaleMigration note
Email APIPOST /v1/sendMap From, To, Subject, HtmlBody, TextBody, Tag, and Metadata into Postscale fields.
Message StreamsTags and domainsTags can preserve a stream label; they do not reproduce Postmark Message Stream isolation.
Inbound webhookInbound Email APIPoint MX at Postscale and keep reply routing identifiers in aliases or metadata.
TemplatesPostscale templatesUse template slugs or UUIDs and pass variables in the send request.
SuppressionsSuppression APIExport suppressions per message stream and preserve stream context with scoped unsubscribe columns when needed.

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.

Postmark
await fetch("https://api.postmarkapp.com/email", {
  method: "POST",
  headers: {
    "X-Postmark-Server-Token": process.env.POSTMARK_TOKEN,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    From: "Acme <alerts@example.com>",
    To: "user@example.com",
    Subject: "Welcome",
    HtmlBody: "<p>Hello from Acme</p>",
    Tag: "onboarding",
    Metadata: { 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

How do Postmark Message Streams map to Postscale?

You can preserve stream names as tags, but tags do not reproduce Postmark Message Stream isolation. Review sending domains, routing, and reputation requirements before migrating.

Can I keep React Email templates?

Yes. Continue rendering HTML in your app and send html_body, or move reusable templates into Postscale when non-developers need to edit content.

Do inbound replies need a new parser?

No. Postscale parses inbound MIME and sends structured webhooks, so your application can keep focusing on routing and ticket logic.

How should Postmark suppressions move?

Export the suppression dump for each message stream, keep stream names when unsubscribe scope matters, and preview the import before commit.

Start your migration to Postscale.