🐙 Check out Postmark's new MCP Server!
x
Comprehensive migration guide from Resend to Postmark.
Two paper airplanes flying

Resend Migration Guide

Everything you need to know about moving from Resend to Postmark.

Table of Contents

Chapter 1

Introduction#

Key differences between Resend and Postmark

Migrating email service providers can be a large undertaking. We want to help relieve some of that stress of moving to Postmark from Resend. This guide will detail some of the differences and similarities between Resend and Postmark, as well as give some useful tips for migrating to Postmark from Resend.

It includes details on differences between Postmark and Resend's APIs, sending outbound emails, processing inbound emails, UI differences, and webhooks.

For quick reference, we have included tables where possible to equate Resend functionality and JSON fields to their comparable functionality and fields in Postmark.

Key differences between Resend and Postmark #

These are some important differences to be aware of when moving over to Postmark from Resend:

  • Postmark separates email traffic through Message Streams. Transactional and broadcast (bulk) traffic does not mix in Postmark, including IP ranges. Resend does not have a concept of separate streams, so all email traffic is sent through the same infrastructure.
  • Postmark supports both REST API and SMTP for sending email. Resend is API-only, which means if any part of your stack depends on SMTP, you'll need to use Postmark's API instead or take advantage of Postmark's SMTP support.
  • Postmark has been delivering transactional email since 2009 with carefully managed IP pools and a reputation built over billions of emails. That history matters—inbox providers give more trust to senders with a long, consistent track record.
  • Postmark includes human support on every plan. Our Customer Success team knows email inside and out, and they're here to help with everything from migration questions to deliverability troubleshooting.
  • Postmark offers inbound email processing that sends the full email content (body, headers, and base64-encoded attachments) directly in the webhook payload. Resend's inbound webhooks send only metadata — you need a second API call to retrieve the actual email content and separate calls for attachments.
  • Postmark provides built-in email templates with a Mustachio-based syntax for variables, conditionals, and loops. If you're using React Email with Resend, you can continue rendering HTML in your app and pass it to Postmark, or migrate to Postmark Templates.
  • We do not recommend using dedicated IPs for most senders but do have that option available if you meet certain eligibility requirements as a sender.

If you need any support during your migration process, please let us know. Our Customer Success team is here to help.


Chapter 2

Postmark Concepts#

Important concepts to learn when moving over to Postmark

There are a few important concepts to learn when moving over to Postmark: Servers, Message Streams, Sender Signatures, and Verified Domains. A server and a confirmed sender signature/verified domain are required for sending, so it is important to understand what they are used for.

Servers #

Each Postmark account contains servers and within those servers are Message Streams. Servers can be thought of as folders you create that group together similar email activity. Each server has its own activity (inbound, transactional, and broadcasts), stats, server API token(s), a unique inbound email address, and templates. You can create as many servers as you need, there is no limit.

Some uses of servers are separating different types of emails such as transactional and broadcasts, separating your clients' activity, emails for different environments (prod, staging, development), or separating sending for your different domains. When you begin adding more users to your Postmark account, you can also assign them access to specific servers so that they can't view email activity or change settings across your entire Postmark account.

In Resend, you manage API keys scoped to your account or a specific domain. In Postmark, the server is the organizational unit—each server has its own API token, templates, and activity. Think of it like having a separate project container for each app or environment.

Message Streams #

Postmark separates email traffic through Message Streams, meaning that transactional and broadcast traffic never intersects in Postmark. Transactional message streams are for messages that are usually unique and triggered by a user action like a welcome email, password reset, or receipts. Transactional streams do not support broadcast messages. Broadcast message streams are for bulk messages sent to multiple recipients at once like announcements, newsletters, or other application emails.

Resend does not have a concept of separate streams for transactional and broadcast email. This is one of Postmark's key advantages—by keeping these types of traffic apart (including at the IP level), your transactional deliverability is protected from any impact of broadcast sending patterns.

Sender Signatures and Verified Domains #

In Postmark you need to have a confirmed sender signature or verified domain for each email address you want to send from. Sender signatures are individual email addresses that are authorized for sending via a confirmation email sent to that address. Adding and verifying a domain using a DKIM record lets you send from any email address on that domain.

We use sender signatures and verified domains to ensure you own or are authorized to send from the mailboxes you add to your Postmark account. You can have as many signatures and domains as you need, there is not a limit. Sender signatures and domains are associated with your account, not a specific server. This means they can be used for sending across all of your account's servers.

This is similar to how Resend requires domain verification before sending. If you've already configured DNS records for Resend, you'll follow a similar process with Postmark's specific DKIM, SPF, and Return-Path values. Since DKIM records use unique selectors per provider, both providers' records can coexist during your transition.


Chapter 3

APIs#

How the Postmark API works

A note on API tokens in Postmark #

Each Postmark account has an account API token. Every server in an account also has its own server API token(s). Server API tokens are used for server-level actions such as sending email, getting statistics, modifying a template, etc. Account API tokens are used for account-level actions such as creating a new server or adding a new domain for sending.

In Resend, you generate API keys that are scoped to your account or a specific domain. In Postmark, the server API token is what you'll use most often—it's the equivalent of your Resend API key for sending email and managing server-level resources.

Check out our help article on the different API Tokens in Postmark for more information.

APIs Map #

API typeResend API namePostmark API name
Sending emailsEmailsEmail
Sending batch emailsBatch EmailsBatch Email
Managing bouncesBounce
Managing templatesTemplates
Managing sending settingsServer
Managing serversServers
Managing sent emailsEmails (Get)Messages
Managing inbound emailsMessages
Manage email domainsDomainsDomains
Manage email addressesSender Signatures
Sending statisticsStats
Managing API keysAPI KeysAPI Tokens (managed in UI or Account API)
Managing audiences/contactsAudiences, Contacts
Managing broadcastsBroadcastsBulk Email API / Broadcast Streams
Managing suppressionsSuppressions

API Libraries #

In addition to the official libraries offered by Postmark, we also include community submitted libraries for additional language/framework options.

API Libraries Map #

 

Language/FrameworkResend official libraryPostmark official libraryPostmark community library
Node.jsResend Node.jsPostmark.jsNode Email Templates
PythonResend PythonPostmarker, pystmark
RubyResend RubyPostmark Ruby
PHPResend PHPPostmark PHP
GoResend GoPostmark Golang, Postmark.go
JavaResend JavaPostmark Java
ElixirResend ElixirSwoosh
C# / .NETPostmark .NET
RailsPostmark Rails
LaravelLaravel Postmark Driver
WordPressPostmark for WordPress
Postmark CLIPostmark CLI

Chapter 4

Sending Outbound Emails#

Start sending through Postmark

Similarities to Resend

  • Sending via a REST API is supported by both services.
  • Both services require domain verification before sending.
  • Both support sending HTML, plain text, or both in the same email.
  • Both support attachments, custom headers, and reply-to addresses.
  • Both offer batch sending for multiple messages in a single API call.
  • Like Resend's test mode, you can send test emails to Postmark's black hole email address, test@blackhole.postmarkapp.com. Postmark also offers a Sandbox mode and a test token (POSTMARK_API_TEST) that validates API calls without sending.

Differences from Resend

  • Postmark supports both REST API and SMTP for sending. Resend is API-only.
  • Postmark uses PascalCase for API field names (e.g., HtmlBody), while Resend uses snake_case (e.g., html).
  • Postmark's To, Cc, and Bcc fields accept comma-separated strings. Resend uses arrays.
  • Postmark supports up to 50 recipients per message and 500 messages per batch API call. Resend supports up to 50 recipients and 100 messages per batch.
  • Postmark's outbound message size limit is 10 MB including attachments.
  • Postmark requires a MessageStream parameter to specify which stream (transactional or broadcast) you're sending through. If not specified, messages default to the transactional stream.
  • Postmark does not have a hard rate limit for requests/second when sending email.

Configuration for sending via SMTP #

Resend does not support SMTP, so if you're moving from Resend and have other parts of your stack that need SMTP (like a legacy CMS, monitoring tool, or third-party integration), Postmark has you covered.

There are two ways that you can send with SMTP, depending on what your SMTP client offers.

You can use the unique API Token for your server (which acts as both a username and password) and a Header to specify the message stream you're sending through. If a header is not specified, Postmark will send through the default transactional stream.

If you don't have an option to add a custom header during the SMTP send, you can instead use an SMTP Token. An SMTP Token consists of an Access Key (which acts as a username) and a Secret Key (which acts as a password).

SettingPostmark
SMTP endpoint for transactionalsmtp.postmarkapp.com
SMTP endpoint for broadcastssmtp-broadcasts.postmarkapp.com
Port25, 587, or 2525
UsernameServer API Token or Access Key
PasswordServer API Token or Secret Key
AuthenticationPlain text (unencrypted), CRAM-MD5, TLS

 

If you need to whitelist the IPs you connect to Postmark SMTP with, you can find the full list under SMTP endpoints.

Message level options when sending with SMTP #

Postmark uses individual SMTP headers for setting specific options on each message.

OptionPostmark SMTP header
Open trackingX-PM-TrackOpens header
Link trackingX-PM-TrackLinks header
TagsX-PM-Tag header
MetadataX-PM-Metadata- headers
Message StreamX-PM-Message-Stream: (Stream ID)

Sending via API #

Authentication #

When authenticating with the Postmark API for sending emails, you will need to use your server API token in an X-Postmark-Server-Token header. You can get your server API token from the server's API Tokens tab.

In Resend, you use an Authorization: Bearer header with your API key. In Postmark, you'll swap that for the X-Postmark-Server-Token header.

To send through a particular Message Stream within your server when using the API, you'll need to add a MessageStream parameter at the time of sending. This is the Stream ID. If no MessageStream is specified, messages will be sent through the default transactional stream.

Outbound Sending API JSON Fields Map #

FieldResendPostmark
From email addressfromFrom
To email address(es)to (array)To (comma-separated string)
Cc email address(es)cc (array)Cc (comma-separated string)
Bcc email address(es)bcc (array)Bcc (comma-separated string)
Subject linesubjectSubject
HTML bodyhtmlHtmlBody
Text bodytextTextBody
Reply-to email addressreply_toReplyTo
Custom headersheaders (array of objects)Headers (array of {"Name": "...", "Value": "..."})
AttachmentsattachmentsAttachments
Tagstags (array)Tag (single string, max 1,000 chars)
MetadataMetadata (key-value pairs)
Open trackingTrackOpens (boolean)
Link trackingTrackLinks (HtmlOnly, TextOnly, HtmlAndText, None)
Message StreamMessageStream (Stream ID)
Template identifierTemplateId or TemplateAlias
Template dataTemplateModel
Scheduled send timescheduled_at
Send without deliveringUse POSTMARK_API_TEST for your X-Postmark-Server-Token

 

Tip: To set a name when adding a To, From, Cc, or Bcc field with the Postmark API, use this format: "Full Name <email@domain.com>"

Tip: Resend supports multiple tags per message as an array. Postmark supports one tag per message as a string. If you need to track multiple dimensions, use Postmark's Metadata field for additional key-value pairs.

Sending a basic email #

Resend (before): #

curl -X POST https://api.resend.com/emails \
  -H "Authorization: Bearer re_123456789" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "you@yourdomain.com",
    "to": ["user@example.com"],
    "subject": "Welcome aboard",
    "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
  }'

Postmark (after): #

curl -X POST https://api.postmarkapp.com/email \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Postmark-Server-Token: your-server-token" \
  -d '{
    "From": "you@yourdomain.com",
    "To": "user@example.com",
    "Subject": "Welcome aboard",
    "HtmlBody": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    "MessageStream": "outbound"
  }'

Sending with attachments #

Resend (before): #

{
  "from": "you@yourdomain.com",
  "to": ["user@example.com"],
  "subject": "Your invoice",
  "html": "<p>Here's your invoice.</p>",
  "attachments": [
    {
      "filename": "invoice.pdf",
      "content": "base64-encoded-content"
    }
  ]
}

Postmark (after): #

{
  "From": "you@yourdomain.com",
  "To": "user@example.com",
  "Subject": "Your invoice",
  "HtmlBody": "<p>Here's your invoice.</p>",
  "MessageStream": "outbound",
  "Attachments": [
    {
      "Name": "invoice.pdf",
      "Content": "base64-encoded-content",
      "ContentType": "application/pdf"
    }
  ]
}

Tip: Postmark requires a ContentType field on each attachment. Resend infers this from the filename.

Attachment fields map #

FieldResendPostmark
FilenamefilenameName
File content (base64)contentContent
Content typecontent_type (optional)ContentType (required)
Content ID (for inline images)ContentID

Batch sending #

Resend supports batch sending through its /emails/batch endpoint (up to 100 messages). Postmark offers the same through /email/batch, supporting up to 500 messages per call.

Each message in the batch is validated and sent independently, so one failed message won't block the rest.

Postmark batch example: #

curl -X POST https://api.postmarkapp.com/email/batch \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Postmark-Server-Token: your-server-token" \
  -d '[
    {
      "From": "you@yourdomain.com",
      "To": "user1@example.com",
      "Subject": "Your weekly summary",
      "HtmlBody": "<p>Here is your summary.</p>",
      "MessageStream": "outbound"
    },
    {
      "From": "you@yourdomain.com",
      "To": "user2@example.com",
      "Subject": "Your weekly summary",
      "HtmlBody": "<p>Here is your summary.</p>",
      "MessageStream": "outbound"
    }
  ]'

Sending with templates #

If you're using React Email with Resend, you have two options for migrating to Postmark.

Option A: Keep rendering HTML in your app. If you're rendering React Email templates to HTML in your application code, you can continue doing that and pass the rendered HTML to Postmark's HtmlBody field. No template migration needed—just update the sending call.

Option B: Use Postmark Templates. Postmark's built-in Templates let you manage your email content in the Postmark app or via the API. Templates use a Mustachio syntax for variables:

<h1>Welcome, {{name}}!</h1>
<p>Thanks for signing up for {{product_name}}.</p>

{{#if order_id}}
  <p>Your order #{{order_id}} has been confirmed.</p>
{{/if}}

Send with a template:

curl -X POST https://api.postmarkapp.com/email/withTemplate \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Postmark-Server-Token: your-server-token" \
  -d '{
    "From": "you@yourdomain.com",
    "To": "user@example.com",
    "TemplateAlias": "welcome-email",
    "TemplateModel": {
      "name": "Jordan",
      "product_name": "Awesome App"
    },
    "MessageStream": "outbound"
  }'

The advantage of Postmark Templates: your team can update email content without deploying code.

SDK examples #

If you're using Resend's official SDK, you'll swap it for Postmark's. Here's what that looks like.

Node.js — Resend (before): #

import { Resend } from 'resend';
const resend = new Resend('re_123456789');

await resend.emails.send({
  from: 'you@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Welcome aboard',
  html: '<h1>Welcome!</h1>',
});

Node.js — Postmark (after): #

import postmark from 'postmark';
const client = new postmark.ServerClient('your-server-token');

await client.sendEmail({
  From: 'you@yourdomain.com',
  To: 'user@example.com',
  Subject: 'Welcome aboard',
  HtmlBody: '<h1>Welcome!</h1>',
  MessageStream: 'outbound',
});

Install the Postmark library: npm install postmark

Python — Resend (before): #

import resend

resend.api_key = "re_123456789"

resend.Emails.send({
    "from": "you@yourdomain.com",
    "to": ["user@example.com"],
    "subject": "Welcome aboard",
    "html": "<h1>Welcome!</h1>",
})

Python — Postmark (after): #

from postmarker.core import PostmarkClient

client = PostmarkClient(server_token='your-server-token')

client.emails.send(
    From='you@yourdomain.com',
    To='user@example.com',
    Subject='Welcome aboard',
    HtmlBody='<h1>Welcome!</h1>',
    MessageStream='outbound',
)

Install the Postmark library: pip install postmarker

To start sending quickly with Postmark's API, be sure to check our official and community API libraries.


Chapter 5

Processing Inbound Email#

Migrating your inbound email handling

Both Resend and Postmark support receiving and processing inbound emails. Both services process incoming emails for your domain, parse the contents, and send a POST request to a webhook URL you specify. However, there are some important architectural differences between the two.

Similarities

  • Both Resend and Postmark process inbound emails and notify your application via webhooks.
  • Both support using a custom domain for receiving emails by adding MX records to your DNS.
  • Both provide a default inbound address you can use without custom domain setup. In Resend, this is a .resend.app address. In Postmark, each server gets a unique @inbound.postmarkapp.com address.
  • Both support receiving emails for any address at your inbound domain and routing based on the to field.

Differences

  • Resend's inbound webhook sends only metadata (sender, recipient, subject, attachment IDs) — it does not include the email body, headers, or attachment content in the webhook payload. You need to make a second API call to the Received Emails API to retrieve the actual email content, and a separate call to the Attachments API for attachment files. This two-step design is intended to support serverless environments with limited request body sizes.
  • Postmark's inbound webhook sends the full email content in a single POST — including the HTML body, text body, headers, and base64-encoded attachments. This means you can process the complete email in one step without making additional API calls.
  • Postmark normalizes all email content to UTF-8, so you don't need to worry about character encoding from different mail clients.
  • Postmark's StrippedTextReply field extracts just the reply text without quoted content, which is useful for building in-app messaging or support ticket features. With Resend, you'd need to parse the raw email content yourself to extract the reply.
  • Postmark provides a MailboxHash field for routing replies to the correct thread by embedding identifiers in the email address (e.g., yourhash+order-12345@inbound.postmarkapp.com).
  • Postmark includes SpamAssassin headers for spam filtering on inbound messages.
  • Postmark's inbound message size limit is 35 MB including attachments.
  • If your webhook returns a non-200 response, Postmark retries up to 10 times over a 10.5-hour period with growing intervals. A 403 response stops retries immediately. Resend also retries failed webhook deliveries and stores emails in the dashboard even if your endpoint is down.

Inbound setup #

In Resend, you configure inbound by either using your default .resend.app domain or adding MX records for a custom domain, then setting up a webhook for the email.received event.

In Postmark, there are two options:

Option A: Use your Postmark inbound address. Each server you create in Postmark comes with a unique inbound email address (e.g., yourhash@inbound.postmarkapp.com). You can forward emails to this address or use it directly.

Option B: Inbound domain forwarding. If you want to receive emails at your own domain (e.g., replies@yourdomain.com), you can set up inbound domain forwarding by adding an MX record to your DNS. You do not need to use a verified sending domain for inbound — the MX record is all that's required.

Inbound Processing JSON Fields Map #

Email propertyResendPostmark
HTML bodyRequires separate API call (Received Emails API)HtmlBody (included in webhook)
Plain text bodyRequires separate API call (Received Emails API)TextBody (included in webhook)
Subject linedata.subjectSubject
To email address(es)data.to (array)To, ToFull → Email
From email addressdata.fromFrom, FromFull → Email
Cc email address(es)data.cc (array)Cc, CcFull → Email
Bcc email address(es)data.bcc (array)Bcc, BccFull → Email
Reply-to email addressReplyTo
Datedata.created_atDate
Message identifierdata.email_idMessageID
Message-ID headerdata.message_idHeaders → Message-ID
Attachment metadatadata.attachments (IDs and filenames only)Attachments → Name, ContentType, ContentLength
Attachment contentRequires separate API call (Attachments API → download_url)Attachments → Content (base64, included in webhook)
Email headersRequires separate API call (Received Emails API)Headers (included in webhook)
TagTag
Mailbox hash (for routing)MailboxHash
Stripped reply textStrippedTextReply
SpamAssassin scoreHeaders → X-Spam-Score
Spam statusHeaders → X-Spam-Status

Postmark inbound processing libraries and code examples #

Language/FrameworkLibrary/Code example
RailsGriddler Postmark
RubyPostmark mitt (gem), Sample application
PHPPostmark inbound PHP
PythonPostmark Inbound Python, postmarker
.NETC# + MVC Inbound Demo

Chapter 6

Webhooks#

Migrating your webhook handlers to Postmark

Both Resend and Postmark allow you to receive notifications as JSON POSTs to URLs you specify when specific events occur. Resend configures webhooks through the dashboard or API, where you select which event types to listen for on a single webhook endpoint. Postmark splits up event types into multiple webhooks, which allows for some additional flexibility and separation of concerns when developing and setting URLs for receiving webhooks.

Webhook Types Map #

Event typeResendPostmark
Deliveryemail.deliveredDelivery webhook
Bouncesemail.bouncedBounce webhook
Spam complaintsemail.complainedSpam complaint webhook
Open trackingemail.openedOpen tracking webhook
Click trackingemail.clickedClick tracking webhook
Inbound processingemail.receivedInbound webhook
Subscription changesSubscription Change webhook

 

Delivery webhook #

Postmark's delivery webhook allows you to receive notifications when an email is delivered to a recipient. In Postmark, an email is considered successfully delivered when the destination email server returns a 250 OK response after delivery is attempted.

Postmark Delivery webhook Fields #

ParameterResendPostmark
Recipient's email addressdata.toRecipient
Delivery timecreated_atDeliveredAt
Email identifierdata.email_idMessageID
Webhook typetypeRecordType
Tagdata.tagsTag
Server used to send the emailServerID
MetadataMetadata
Message StreamMessageStream
Receiving server responseDetails

  #

Bounce webhook #

Postmark includes some additional information for bounce events that is not present in Resend's webhook:

  • From email address and subject of the email
  • Unique identifier for the bounce (used to reactivate a bounced email address using the Postmark Bounce API)
  • Information on whether the recipient's email address is deactivated and can be reactivated
  • Whether a message dump is available. Postmark stores content for 45 days as standard (and retention can be customized from 7 to 365 days), but retains bounce information indefinitely.

Bounce webhook Fields Map #

ParameterResendPostmark
Recipient's email addressdata.toEmail
From email addressdata.fromFrom
Email subject lineSubject
Bounce timestampcreated_atBouncedAt
Bounce type/reasonType/Name
Bounce codeTypeCode
Email identifierdata.email_idMessageID
Webhook typetypeRecordType
Tagdata.tagsTag
MetadataMetadata
Message StreamMessageStream
Server used to send the emailServerID
Unique bounce identifierID
Bounce detailsDetails
Description of bounceDescription
Whether recipient email is deactivatedInactive
Whether email address can be reactivatedCanActivate
If a message dump is availableDumpAvailable

Tip: Postmark includes an additional option when setting your bounce webhook URL to include the message content in the JSON sent to your URL. This option lets you receive the full message content when receiving bounce event information.

Rebound #

The Rebound JavaScript snippet (once installed on your website) will tap into the Postmark API to check for hard bounces and prompt your customers to update their email address if they've experienced deliverability issues in the past. Resend does not have an equivalent feature.

Screenshot of rebound JavaScript snippet
You can even customize this notifications appearance and messaging without writing any code.

Open tracking webhook #

You will notice some open tracking information available with the Postmark open tracking webhook that does not exist in Resend's webhook:

  • The platform the recipient was using (mobile, desktop, webmail)
  • The geographic location the recipient was in, including the region, country, city, zip code, and coordinates
  • The email client or browser the recipient was using
  • Whether this open event was the first time the email was opened

Open tracking webhook fields map #

ParameterResendPostmark
Recipient's email addressdata.toRecipient
Timestamp of opencreated_atReceivedAt
Email identifierdata.email_idMessageID
Webhook typetypeRecordType
Tagdata.tagsTag
MetadataMetadata
Message StreamMessageStream
User agentUserAgent
Operating systemOS
Platform (mobile, desktop, webmail)Platform
Email clientClient
IP addressGeo → IP
Geographic locationGeo
First open for this emailFirstOpen

Click tracking webhook #

You will notice some click tracking information available with the Postmark click tracking webhook that does not exist in Resend's webhook:

  • The platform the recipient was using when they clicked the link
  • The geographic location of the recipient
  • The email client or browser and version the recipient was using

Click tracking webhook fields map #

ParameterResendPostmark
Recipient's email addressdata.toRecipient
URL that was clickedOriginalLink
Timestamp of clickcreated_atReceivedAt
Email identifierdata.email_idMessageID
Webhook typetypeRecordType
Tagdata.tagsTag
MetadataMetadata
Message StreamMessageStream
User agentUserAgent
Operating systemOS
PlatformPlatform
Email clientClient
IP addressGeo → IP
Geographic locationGeo
Click location (HTML or text)ClickLocation

  #

Spam Complaint webhook #

Postmark includes some additional spam complaint information that does not exist in Resend's webhook:

  • From email address and subject of the email
  • Whether a message dump is available
  • Whether the recipient's email address can be reactivated

Spam complaint webhook fields map #

ParameterResendPostmark
Recipient's email addressdata.toEmail
From email addressdata.fromFrom
Email subject lineSubject
Complaint timestampcreated_atBouncedAt
Email identifierdata.email_idMessageID
Webhook typetypeRecordType
Tagdata.tagsTag
MetadataMetadata
Message StreamMessageStream
Server used to send the emailServerID
Unique bounce identifierID
Bounce codeTypeCode
Complaint detailsDetails/Description
Whether recipient email is deactivatedInactive
Whether email address can be reactivatedCanActivate
If a message dump is availableDumpAvailable

  #

Subscription change webhook #

The Subscription Change webhook is triggered when an email address is added or removed from a Message Stream's Suppression list. These event notifications are specific to the following subscription changes: hard bounces, spam complaints, and manual suppressions. Resend does not have an equivalent webhook.

Subscription change webhook fields map #

ParameterPostmark
Webhook typeRecordType
Server used to send the emailServerID
Message StreamMessageStream
MetadataMetadata
Recipient email addressRecipient
Timestamp of the subscription changeChangedAt
Who triggered the change (Recipient, Customer, Admin)Origin
Whether the change was a deactivation or reactivationSuppressSending
Reason address was added to the Suppression listSuppressionReason
TagTag

  #


Chapter 7

UI Overview#

Getting familiar with the Postmark web app

When you log into Postmark you are placed in the Servers page, which shows each server you have created. Each server you create has a default transactional message stream for outbound sending and an inbound message stream for processing inbound email. Each server has tabs for Message Streams, Templates, API Tokens, and Settings. Each message stream has tabs for Statistics, Activity, Setup Instructions, and Settings, which are unique for each message stream.

If you're coming from Resend, you'll notice that Postmark's UI is organized around servers rather than a single dashboard. This gives you more granular control over how you organize and monitor your email activity.

Servers #

Servers let you separate your transactional, broadcasts, and inbound message streams, templates, and credentials based on domains, environments, customers, or any other criteria that helps organize the activity of a given application or website.

The main servers page will show you a list of your servers. You can create as many servers as you need, there is no limit. You can also pin your most frequently accessed servers so they appear at the top of the list. Unused servers will be greyed out, for easy identification of which servers you may want to delete or repurpose.

A screenshot of Postmark's servers.
You can use servers in Postmark to group logically related email activity by domains, environments, or other factors.
Screenshot of server settings featuring the server name, a color, SMTP settings, link and open tracking, and the option to delete the server.
The main server settings let you rename your server as well as change the server's representative color, turn on SMTP for the server, and turn on/off Open/Link tracking..

Statistics #

To view detailed statistics and metrics for a server's message streams, locate the server in the servers list or by using the search field. Click on the bar graph icon and select the server's message stream (inbound, transactional, or broadcasts) you are interested in to be taken to its overview page.

The Statistics page shows sending volume, link tracking metrics (if enabled), open tracking metrics (if enabled), and bounce/spam complaint metrics. Statistics can be filtered by date and tag to show the levels of engagement for various groups of emails or all emails.

Screenshot of accessing a message stream's statistics.
To view detailed statistics and metrics for a server's message streams, locate the server in the servers list or by using the search field. Click on the bar graph icon and select the server's message stream (inbound or outbound) you are interested in to be taken to its overview page.
Screenshot of a transactional message stream's statistics tab.
Statistics can be filtered by date and tag to show the levels of engagement for various groups of emails or all emails.

Activity #

To see your inbound, transactional, and broadcast activity in a server, select the message stream you are interested in and click on the Activity tab. This area will show a detailed event view of the stream's events, including sent, delivered, open events, spam complaints, bounces, etc. Use the search bar to look for emails by subject or email address.

Events in Activity are color coded to help you tell what occurred at a glance:

  • Email processed - light green
  • Email delivered - green
  • Email opened - blue
  • Link clicked - purple
  • Bounce/spam complaint - red
  • Message queued - yellow

In addition to message events, Postmark stores the full content (both plain text and HTML) of emails for 45 days as standard (and retention can be customized from 7 to 365 days). When an email bounces, Postmark provides a detailed explanation from the server response as well as the option to reactivate delivery.

Screenshot of an example transactional stream activity feed showing emails sent, opened, clicked, bounced, or marked as spam.
The events activity stream will show emails, opens, bounces, clicks, and spam complaints.
Screenshot of the detailed view of an email.
In addition to message events, Postmark stores the full content (both plain text and HTML) of emails for 45 days as standard.
Screenshot of an email with a bounce notification and the option to reactivate.
When an email bounces, Postmark provides a detailed explanation from the server response as well as the option to reactivate delivery. You can also reactivate delivery for bounced addresses using the API.

Suppressions #

Within each Message Stream in Postmark, you'll see a Suppressions tab. This tab shows all inactive addresses for that stream, as well as the reason why they're inactive—and if possible, a button to reactivate them.

Addresses in Postmark can be automatically suppressed for three reasons: due to a hard bounce, a spam complaint, or an unsubscribe. You can also manually add recipients to the Suppression list (up to 50 at a time) per Message Stream.

Unlike some providers, each email you attempt to send to a suppressed address does not consume any credits.

With the Subscription Change Webhook, you can be notified when an address is added or removed from a Stream Suppression list. You can also manage, add, and delete suppressions via API.

Templates #

Postmark gives you the ability to create and store templates including a variety of pre-built and well-tested templates for common scenarios. From the Templates tab you can create, edit, and delete the server's templates. Each server contains its own templates but you can easily copy templates from one server to another.

Alternatively, if you'd like to build your own batch of templates, we've created and open-sourced MailMason to help you automate the process of creating, testing, and managing your own templates using partials, variables, SASS, and asset management.

Screenshot of the choice of templates or the option to code your own templates.
Postmark includes a variety of pre-built and well-tested templates to make getting started easier. They include Welcome emails, Password reset, Receipts, Invoices, and more.

API Tokens #

The API Tokens tab shows you your server API token(s). Use this tab to generate and delete server API tokens. Server API Tokens are used for outbound sending, SMTP authentication, and making server level API calls. A Server can have up to 3 active API Tokens.

Screenshot of example server credentials for the server API.
The Server credentials tabs provides a unique API token for the server.

Managing Account Settings #

The Account page is where you can:

  • Require all account users to use 2FA.
  • Add emergency contacts in case we need to reach you regarding your account and have not heard back from the owner.
  • Set up billing notifications.
  • Mange your account API tokens.
  • Manage your your bill and billing details.
Screenshot of account settings like requiring 2FA, emergency contacts, and billing notification contacts.
From the account settings, you can require 2FA, add emergency contacts as well as billing notification contacts.

Users and permissions #

The Users page is where you add and manage users to your account for tasks such as viewing activity for troubleshooting and tracking purposes, managing server settings, creating templates, etc. Use our different roles to effectively manage the security of your account. See our help article on setting permissions for an overview of what options there are and how to control your users' permissions.

Screenshot of the users and permissions list with an owner and an admin showing server-level permissions.
Users and permissions can be managed to allow full or read-only access to individual servers.
Screenshot of advanced user permissions management.
You can control whether someone has access to the full account or individual servers, and with each individual server, you can control whether they have full access or read only access.

Chapter 8

Conclusion#

It’s time to switch

Tips for a smooth migration #

Run both providers in parallel. There's no need to flip the switch all at once. Route a subset of your email through Postmark first—maybe your password reset emails—and verify delivery before migrating everything.

Watch your DNS records. During the transition, you can have DNS records for both Resend and Postmark active. DKIM uses unique selectors per provider, so they won't conflict. Once you've fully migrated, clean up the old records.

Update your suppression lists. If you've accumulated bounces or unsubscribes in Resend, make sure those addresses are handled in Postmark too. You can add suppressions through the Suppressions API or manage them in the Postmark app.

Set up your Message Streams. If you're sending both transactional and marketing email, take advantage of Postmark's Message Streams to separate them. This protects your transactional reputation from any broadcast-related bounces or complaints.

Dive deeper #

For more Postmark specific insight on how to get started and get the most out of Postmark, make sure to look through our "Getting Started Guide" or visit our support center where you can easily search all of our documentation from a single place. API docs. Guides. Blog posts. Help docs. Labs projects. You name it. We probably have something that can help you out.

Status information #

Once you've switched to Postmark, you may want to become familiar with our status page and status API. We believe deeply in transparency, and we go a step further than just system availability and share our inbox rates and delivery speeds for the five most popular inbox providers. We also offer all of the data via an API so you can monitor us and set up automation in the event something does go wrong.

Say hello! #

We love to help. Feel free to reach out through our contact form or via Twitter (@postmarkapp).

Welcome aboard #

You now have a solid understanding of how to transition over the core features you need in an ESP and how to move from Resend to Postmark, including how to send outbound and process inbound email, what APIs and webhooks to use for certain functions, and how to view your email activity and statistics. If you have any questions about where to find a setting or how to use a feature in Postmark, get in touch and we can help!

Still have questions?

  • Ignacio Roig Ignacio

Ask us anything! We’re eager to help you with any problem or question you have…

Contact us