Skip to content

Postmark

Postmark focuses purely on transactional email and is known for fast, reliable inbox delivery. It separates transactional and bulk traffic into message streams, which protects the reputation of your important emails.

Choose Postmark when deliverability and speed of transactional mail (password resets, receipts, form confirmations) matter most and you don’t mind that Postmark reviews new accounts before they can send freely. Postmark does not allow cold or purchased-list marketing. See the services overview for alternatives.

  • A Postmark account and a server (Postmark’s name for a project), e.g. “Website”.
  • A verified sender: either a Sender Signature for a single address or, better, a verified domain (Sender Signatures → Add Domain or Signature).
  • Account approval before sending to recipients outside your own domain – see Sandbox & limits.
  • The Server API token of that server (Servers → your server → API Tokens). A server token can only send and read data of its own server – that is the least-privilege option. Do not use the Account API token.
  1. Open Email services → Add service → Postmark.
  2. Fill in the fields:
Field Where to find it Example
Server API token Servers → your server → API Tokens a1b2c3d4-e5f6-7890-abcd-ef1234567890
Message stream Servers → your server → Message Streams; use a Transactional stream outbound
Webhook username Optional – the Basic auth username you set on the Postmark webhook frontmail
Webhook password Optional – the matching password s3cr3t-long-random
Max emails per second Optional; default 10/s 10
  1. Click Verify & save – Frontmail reads the server details with the token.
  2. The service is saved once the check passes. Credentials are encrypted with AWS KMS envelope encryption.

After you add a domain, Postmark shows two records to publish:

; DKIM – the selector contains a date-based part, copy it from Postmark
20240101123456pm._domainkey.example.com. TXT "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GN…"
; Custom Return-Path – makes SPF align with your domain
pm-bounces.example.com. CNAME pm.mtasv.net.
; DMARC – monitoring first
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
  • The DKIM host looks like <timestamp>pm._domainkey; always copy the exact value from Postmark.
  • With the Return-Path CNAME to pm.mtasv.net, you do not need to add Postmark to your root SPF record – SPF is checked on the Return-Path subdomain, which Postmark manages.
  • Click Verify next to each record in Postmark. Tighten DMARC to p=quarantine / p=reject once reports are clean.

Postmark has a single API endpoint (api.postmarkapp.com) and no region to choose. Data is processed in the US; check Postmark’s DPA if EU data residency matters to you.

  • Pending approval: a new account can send only to addresses on the same domain as the verified sender until Postmark approves it. Attempts to send elsewhere fail with error code 412. Request approval in the Postmark dashboard; it is usually handled within a business day.
  • Test mode: the special token POSTMARK_API_TEST accepts messages without sending them – useful for local testing, but Frontmail’s Test connection will reject it because it has no server behind it.
  • Free developer plan: 100 emails per month.
  • Postmark keeps its own list of inactive recipients (hard bounces, complaints) per stream; sending to them fails with code 406.

Postmark webhooks are configured per message stream.

  1. Copy the webhook URL from the service page in Frontmail (copy button):

    https://api.frontmail.dev/webhooks/providers/postmark/<token>
  2. In Postmark open Servers → your server → the stream (e.g. Default Transactional Stream) → Webhooks → Add webhook, paste the URL and select the events:

Postmark event Frontmail event
Delivery delivered
Bounce – hard (HardBounce, BadEmailAddress, ManuallyDeactivated) bounced – added to the suppression list
Bounce – soft/transient (SoftBounce, Transient, DnsError) recorded on the message
Spam Complaint complained – added to the suppression list
Open opened (enable open tracking on the stream)
Link Click clicked (enable link tracking on the stream)
  1. Protect the webhook with Basic auth (recommended): in the webhook form fill in Basic auth credentials (username + a long random password) and enter the same values in the Frontmail service fields Webhook username / Webhook password.

Signature verification: Postmark does not sign webhook payloads. The secret token in the URL identifies the service, and when you set a webhook password Frontmail rejects any request without matching Basic auth credentials. Use the Send test button in Postmark to check it.

Frontmail adds an X-Frontmail-Message-Id header to each message so events match the right message.

  • auth – the service is broken (invalid token, unconfirmed sender, account not approved, unknown stream). The service is marked unhealthy; the owner gets an email and a dashboard banner. A fallback service on the template takes over; without one the credit is refunded and the message waits in the hold queue as held_service_error, sent automatically after you fix the service (re-checked on save and by the daily health check).
  • permanent – this message can’t be sent (invalid or inactive recipient, validation error). Fallback service if configured, otherwise failed and the credit refunded.
  • transient – 5xx, timeouts, 429. Retried with exponential backoff; when retries run out failed and refunded.
Postmark error Class What to do
10 – Bad or missing Server API token (HTTP 401) auth Copy the Server token (not the Account token) again.
400 – Sender signature not defined for From address auth Verify the From domain/address in Sender Signatures, or change the template’s From.
401 – Sender signature not confirmed auth Click the confirmation link Postmark sent to the sender address.
412 – Account pending approval, recipients restricted to your domain auth Request account approval in Postmark.
1235 – Message stream not found auth Fix the Message stream ID (e.g. outbound).
406 – Inactive recipient permanent The address bounced or complained earlier; Postmark suppresses it. Reactivate it in Postmark only if you’re sure.
300 / 422 – Invalid email request / invalid address permanent See invalid recipient.
HTTP 429 / 500 / 503 transient Rate limit or outage – Frontmail retries automatically.
  • Domain verified in Postmark (DKIM TXT + Return-Path CNAME pm.mtasv.net)
  • DMARC record published, starting with p=none
  • Account approved by Postmark
  • Server API token (not Account token) entered
  • Message stream = a transactional stream (outbound)
  • Test connection passes
  • Webhook on the stream with Delivery, Bounce, Spam Complaint (+ Open/Click)
  • Basic auth on the webhook, same credentials in Frontmail