> ## 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 Resend

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

## Why migrate

Resend 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, and TLS is always-on for every message. Resend's API uses familiar Bearer-auth and JSON patterns, so the switch is a small refactor for developers already comfortable with Resend.

## What stays the same

* REST API over HTTPS with JSON request bodies
* API key authentication via the `Authorization: Bearer` 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 | Resend | Paubox Email API |
| :- | :- | :- |
| Base URL | `https://api.resend.com/emails` | `https://api.paubox.com/v1/email/messages` |
| Auth header | `Authorization: Bearer $RESEND_API_KEY` | `Authorization: Bearer $PAUBOX_API_KEY` |
| Request body shape | `from`, `to`, `subject`, `html` flat keys | `data.message` object with `headers` and `content` keys |
| Recipients field | `to` (array of strings) | `recipients` (array of strings, nested under `data.message`) |
| SMTP host | `smtp.resend.com` | `smtp.paubox.com` |
| SMTP username | `resend` (literal) | `apikey` (literal) |
| SMTP port | 465 (recommended), 587, 25 | 587 (also supports 465, 25) |
| Webhook events | email.sent, email.delivered, email.bounced, email.opened, email.clicked, email.complained, email.delivery\_delayed | delivered, opened, temporary\_failure, permanent\_failure |
| Batch send | `/emails/batch` endpoint | `/bulk_messages` endpoint, recommended max 50 per request |
| TLS enforcement | Optional | Always-on, cannot be disabled |
| BAA available | No | Yes (signed with every customer) |

## Send a single email

<CodeGroup>
  ```bash Resend (before) theme={null}
  curl -X POST https://api.resend.com/emails \
    -H "Authorization: Bearer $RESEND_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "provider@yourclinic.com",
      "to": ["patient@example.com"],
      "subject": "Your appointment summary",
      "html": "<p>See attached.</p>"
    }'
  ```

  ```bash Paubox (after) theme={null}
  curl -X POST https://api.paubox.com/v1/email/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>

## SMTP configuration

<CodeGroup>
  ```js Resend (before) theme={null}
  const transporter = nodemailer.createTransport({
    host: 'smtp.resend.com',
    port: 465,
    auth: {
      user: 'resend',
      pass: process.env.RESEND_API_KEY,
    },
  });
  ```

  ```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:**

  Two changes are required: update `host` from `smtp.resend.com` to `smtp.paubox.com`, and change the literal username from `resend` to `apikey`.
</Tip>

## Webhook event mapping

| Resend event | Paubox event key | Notes |
| :- | :- | :- |
| `email.delivered` | `api_mail_log_delivered` | |
| `email.opened` | `api_mail_log_opened` | |
| `email.bounced` | `api_mail_log_permanent_failure` | |
| `email.delivery_delayed` | `api_mail_log_temporary_failure` | |
| `email.clicked` | no equivalent | Remove handler or no-op; poll click data via [Get message receipt](/email-api/message-receipt) |
| `email.complained` | no equivalent | Remove handler |
| `email.sent` | no equivalent | Remove handler; `delivered` confirms acceptance |

<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 > Domains](https://next.paubox.com/settings/domains) 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 [API Keys](https://next.paubox.com/settings/api_keys) page, generate an API key. All requests use the base URL `https://api.paubox.com/v1/email`.
  </Step>

  <Step title="Update base URL, auth header, and request body">
    Apply the changes shown in the [Key differences](#key-differences) table and [Send a single email](#send-a-single-email) section above. Note that recipients move from a top-level `to` array into `data.message.recipients`.
  </Step>

  <Step title="Update SMTP credentials">
    If you use the SMTP path, update `host` to `smtp.paubox.com` and change the literal username from `resend` to `apikey`. See [SMTP configuration](#smtp-configuration) above.
  </Step>

  <Step title="Remap or remove webhook handlers">
    Update your webhook endpoint using the [event mapping table](#webhook-event-mapping) above. Remove handlers for `email.clicked`, `email.complained`, and `email.sent`.
  </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 Resend SPF/DKIM records with the Paubox records shown in your Domains page.
  </Step>

  <Step title="Revoke Resend API keys">
    Once traffic has fully moved to Paubox, revoke your Resend API keys.
  </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>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.