Skip to content

Testing Postmark without emailing anyone, POSTMARK_API_TEST vs sandbox servers vs bounce-testing

Postmark has three ways to send without reaching a real inbox. Each tests something different. Pick by what you need to prove.

Postmark3 min readships at docs/solutions/postmark/testing-with-postmark-api-test-and-sandbox.md

Tags: postmark · testing · sandbox · ci · local-development · bounces

You want CI to exercise the email path. You do not want CI to email real people. Postmark gives you three tools, and they are not interchangeable.

1. The POSTMARK_API_TEST token

Set the server token to the literal string POSTMARK_API_TEST.

POSTMARK_SERVER_TOKEN=POSTMARK_API_TEST
  • Postmark validates the request exactly as it would a real one.
  • It answers with a normal response and a MessageID.
  • Nothing is delivered. Nothing appears in the activity feed. No webhook fires.

Good for: local development, CI, unit-ish tests of the real HTTP path. A malformed address, a missing body, a metadata limit and a bad header all still fail.

Not good for: anything after the API call. You cannot test bounces, webhooks or what the email looks like.

Tell people when it is on. A log line on each send saves someone refreshing an inbox for ten minutes:

if (process.env.POSTMARK_SERVER_TOKEN === "POSTMARK_API_TEST") {
  console.warn("[email] POSTMARK_API_TEST token: validated, not delivered");
}

Server-only reads (like GET /server) are not a use for it. Skip those checks when the test token is set rather than reporting them as failures.

2. A sandbox server

When you create a server you can choose Sandbox delivery. It cannot be changed later.

  • Sends are processed and appear in the activity feed with full content.
  • Nothing leaves Postmark.
  • Webhooks can be tested from the dashboard.

Good for: staging, QA, previewing what was actually sent, demo environments that must never mail a customer.

Make it a separate server with its own token. Never flip production into a test mode.

3. The bounce-testing domain

On a live server, send to @bounce-testing.postmarkapp.com:

  • hardbounce@bounce-testing.postmarkapp.com produces a hard bounce.
  • Postmark records a real bounce event and fires your Bounce webhook.
  • Fake bounces count toward your monthly volume but not toward your bounce rate.

Good for: proving the full loop. Send, bounce, webhook, address suppressed, next send refused.

Which to use

You want to proveUse
The request is validPOSTMARK_API_TEST
The rendered email looks right, in contextSandbox server, or a real send to yourself
Your webhook handles a bouncebounce-testing address on a live server
It lands in the inboxA live server and a real mailbox you own

Do not

  • Do not mock the SDK and call it an email test. It proves your mock works.
  • Do not point CI at a live token "just for a few tests". One bad fixture mails every address in it.
  • Do not use real customer addresses in fixtures. Use example.com (reserved for this) or the bounce-testing domain.