> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paubox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from Postmark

> Switch from Postmark to the Paubox Email API for HIPAA-compliant transactional email.

## Why migrate

Postmark does not sign Business Associate Agreements (BAAs). HIPAA requires a signed BAA with any vendor that handles Protected Health Information (PHI) in transit, including transactional email providers. Paubox is purpose-built for HIPAA-compliant email and signs a BAA with every customer. The Postmark API uses familiar REST/JSON patterns, so the switch is straightforward for developers already comfortable with Postmark.

## What stays the same

* REST API over HTTPS with JSON request bodies
* API key authentication via a request header
* Domain authentication: SPF and DKIM records required
* SMTP as an alternative to the HTTP API
* Webhook-based event notifications for delivery status

## Key differences

| Dimension          | Postmark                                                         | Paubox Email API                                          |
| :----------------- | :--------------------------------------------------------------- | :-------------------------------------------------------- |
| Base URL           | `https://api.postmarkapp.com/email`                              | `https://api.paubox.net/v1/$PAUBOX_ENDPOINT/messages`     |
| Auth header        | `X-Postmark-Server-Token: $TOKEN`                                | `Authorization: Bearer $PAUBOX_API_KEY`                   |
| Request body shape | `From`, `To`, `Subject`, `HtmlBody` flat keys                    | `data.message` object with `headers` and `content` keys   |
| SMTP host          | `smtp.postmarkapp.com`                                           | `smtp.paubox.com`                                         |
| SMTP username      | Postmark server token (as username)                              | `apikey` (literal)                                        |
| SMTP password      | Postmark server token (as password)                              | Paubox API key                                            |
| SMTP port          | 587 or 2525                                                      | 587 (also supports 465, 25)                               |
| Webhook events     | Delivery, Open, Click, Bounce, SpamComplaint, SubscriptionChange | delivered, opened, temporary\_failure, permanent\_failure |
| Batch send         | `/email/batch` endpoint, up to 500/request                       | `/bulk_messages` endpoint, recommended max 50 per request |
| TLS enforcement    | Optional                                                         | Always-on, cannot be disabled                             |
| Message streams    | Transactional + Broadcast streams                                | Single unified API (no stream concept)                    |

## Send a single email

<CodeGroup>
  ```bash Postmark (before) theme={null}
  curl -X POST https://api.postmarkapp.com/email \
    -H "X-Postmark-Server-Token: $POSTMARK_SERVER_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "From": "provider@yourclinic.com",
      "To": "patient@example.com",
      "Subject": "Your appointment summary",
      "HtmlBody": "<p>See attached.</p>",
      "MessageStream": "outbound"
    }'
  ```

  ```bash Paubox (after) theme={null}
  curl -X POST https://api.paubox.net/v1/$PAUBOX_ENDPOINT/messages \
    -H "Authorization: Bearer $PAUBOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "message": {
          "recipients": ["patient@example.com"],
          "headers": {
            "subject": "Your appointment summary",
            "from": "provider@yourclinic.com"
          },
          "content": {
            "text/html": "<p>See attached.</p>"
          }
        }
      }
    }'
  ```
</CodeGroup>

<Note>
  **Note:**

  `$PAUBOX_ENDPOINT` is the username shown on your [Paubox Email API > Settings](https://next.paubox.com/emailapi/settings) page, not your email address.
</Note>

## SMTP configuration

<CodeGroup>
  ```js Postmark (before) theme={null}
  const transporter = nodemailer.createTransport({
    host: 'smtp.postmarkapp.com',
    port: 587,
    auth: {
      user: process.env.POSTMARK_SERVER_TOKEN,
      pass: process.env.POSTMARK_SERVER_TOKEN,
    },
  });
  ```

  ```js Paubox (after) theme={null}
  const transporter = nodemailer.createTransport({
    host: 'smtp.paubox.com',
    port: 587,
    auth: {
      user: 'apikey',
      pass: process.env.PAUBOX_API_KEY,
    },
  });
  ```
</CodeGroup>

<Tip>
  **Tip:**

  Note the username change: Postmark uses the server token as both username and password. Paubox uses the literal string `apikey` as username and your API key as password.
</Tip>

## Webhook event mapping

| Postmark event       | Paubox event key                 | Notes                                                                                          |
| :------------------- | :------------------------------- | :--------------------------------------------------------------------------------------------- |
| `Delivery`           | `api_mail_log_delivered`         |                                                                                                |
| `Open`               | `api_mail_log_opened`            |                                                                                                |
| `Bounce` (hard)      | `api_mail_log_permanent_failure` |                                                                                                |
| `Bounce` (soft)      | `api_mail_log_temporary_failure` |                                                                                                |
| `Click`              | No equivalent                    | Remove handler or no-op; poll click data via [Get message receipt](/email-api/message-receipt) |
| `SpamComplaint`      | No equivalent                    | Remove handler                                                                                 |
| `SubscriptionChange` | No equivalent                    | Manage unsubscribes in the Paubox dashboard                                                    |

<Note>
  **Note:**

  Click tracking is available by polling `GET /message_receipt?sourceTrackingId=...`; it is not delivered as a push webhook event.
</Note>

## Migration checklist

<Steps>
  <Step title="Sign a BAA with Paubox">
    Required before go-live. Contact Paubox to initiate the Business Associate Agreement.
  </Step>

  <Step title="Create an account and verify your sending domain">
    Add your domain on the [Paubox Email API > Settings](https://next.paubox.com/emailapi/settings) page and complete the TXT record verification. See the [Quickstart guide](/email-api/quickstart) for step-by-step instructions.
  </Step>

  <Step title="Generate a Paubox API key">
    From the Settings page, generate an API key and note your customer endpoint (`https://api.paubox.net/v1/YOUR_USERNAME`).
  </Step>

  <Step title="Update base URL, auth header, and request body">
    Replace the Postmark endpoint and `X-Postmark-Server-Token` header with the Paubox endpoint and Bearer token. Restructure the request body to use the `data.message` shape shown above.
  </Step>

  <Step title="Remove MessageStream">
    Paubox has no stream concept. Remove the `"MessageStream"` field from all requests.
  </Step>

  <Step title="Update SMTP credentials">
    If you use the SMTP path, update `host` to `smtp.paubox.com`, set `username` to the literal string `apikey`, and `password` to your Paubox API key.
  </Step>

  <Step title="Remap or remove webhook handlers">
    Update your webhook endpoint using the [event mapping table](#webhook-event-mapping) above. Remove handlers for `Click`, `SpamComplaint`, and `SubscriptionChange`.
  </Step>

  <Step title="Remove any code that disables TLS">
    Paubox enforces TLS on every message. Any `allowNonTLS: true` or equivalent settings should be removed.
  </Step>

  <Step title="Send a test message">
    Confirm delivery using the [Get message receipt](/email-api/message-receipt) endpoint with the `sourceTrackingId` returned from your test send.
  </Step>

  <Step title="Swap DNS records">
    Replace Postmark SPF/DKIM records with the Paubox records shown in your Settings page.
  </Step>

  <Step title="Revoke Postmark server tokens">
    Once traffic has fully moved to Paubox, revoke your Postmark server tokens.
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart guide" icon="rocket" href="/email-api/quickstart">
    Full setup walkthrough from account creation to first send
  </Card>

  <Card title="Webhooks reference" icon="webhook" href="/email-api/webhooks">
    Configure delivery event notifications
  </Card>

  <Card title="Batch send" icon="layer-group" href="/email-api/bulk-messages">
    Send up to 50 messages in a single request
  </Card>

  <Card title="SMTP API" icon="server" href="/email-api/smtp">
    Connect via SMTP instead of REST
  </Card>
</CardGroup>
