Email Fast Get a sandbox key
Migrate

Migrate from Postmark

Keep your Postmark client and change the host and token, or adopt our SDK. Your ErrorCode handling keeps working, 406 included.

Facts verified 2026-07-17 — corrections: hello@emailfast.dev

Two ways to switch

Email Fast speaks Postmark's send API natively: SendGrid-, Mailgun-, and Postmark-compatible endpoints: point your existing SDK at a new base URL with a new key and keep your code. The semantics your retry and suppression code depends on are preserved: ErrorCode: 0 on success, 406 for an inactive (suppressed) recipient, 300 for a blocked send, and /email/batch always returning HTTP 200 with per-message results.

Path 1 — keep the postmark package

  import { ServerClient } from "postmark";

- const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN);
+ const client = new ServerClient(process.env.EMAILFAST_API_KEY, {
+   requestHost: "api.emailfast.dev", // ef_sandbox_… works everywhere
+ });

  await client.sendEmail({
    From: "you@yourdomain.com",
    To: "ada@example.com",
    Subject: "Welcome",
    HtmlBody: "<h1>Hi Ada</h1>",
  });

Calling over raw HTTP? Add an Idempotency-Key header and retries become safe:

curl https://api.emailfast.dev/email \
  -H "X-Postmark-Server-Token: ef_sandbox_..." \
  -H "Idempotency-Key: welcome-ada-1" \
  -H "Content-Type: application/json" \
  -d '{ "From": "you@yourdomain.com", "To": "ada@example.com",
        "Subject": "Welcome", "HtmlBody": "<h1>Hi Ada</h1>" }'

Path 2 — adopt @email-fast/nodejs

- await client.sendEmail({
-   From: "you@yourdomain.com",
-   To: "ada@example.com",
-   Subject: "Welcome",
-   HtmlBody: "<h1>Hi Ada</h1>",
- });
+ const ef = new EmailFast({ apiKey: process.env.EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" });
+ await ef.send({
+   to: "ada@example.com",
+   subject: "Welcome",
+   html: "<h1>Hi Ada</h1>",
+   idempotency_key: "welcome-ada-1",
+ });

What maps 1:1

Both endpoints, the server-token header, per-message results on batch, and the ErrorCode contract — including the 406 your code already treats as "stop sending to this address." Every message admitted this way passes the same checkpoint as every other ingress: every send — REST, SMTP, browser SDK, compatibility endpoints, broadcasts, automations — passes through one admission gate: idempotency, suppression, quota, and content policy in a single checkpoint no ingress can skip.

What arms at launch

The hosted data importers — templates, contacts, and suppression lists pulled from your Postmark server — arm at launch. Today you can evaluate the send path end to end with a sandbox key: sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves.

The idempotency bonus

Pass an Idempotency-Key header and each message in a /email/batch call gets its own derived key, so a timeout-and-retry can never double-send part of a batch: a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.

Next

Questions, answered plainly

Do I need to change my application code to migrate from Postmark?

No. POST /email and POST /email/batch are accepted as-is. Put your Email Fast key in the X-Postmark-Server-Token header and change the host — the response bodies stay Postmark-shaped.

Does my ErrorCode handling still work?

Yes. Success returns ErrorCode: 0 with a MessageID; a suppressed recipient returns ErrorCode 406 (HTTP 406 on /email), a blocked send returns ErrorCode 300. /email/batch always answers HTTP 200 with a per-message result array, exactly as Postmark does.

How do I test before pointing production at Email Fast?

Use a sandbox key (ef_sandbox_…) as the server token. The full pipeline runs — validation, rendering, events, a hosted capture inbox — and no email leaves.

See it for yourself

Sandbox keys run the real pipeline dry — real validation, real events, a hosted inbox, no email sent. Early access is onboarding now.