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.
Why migrate
AWS will sign a Business Associate Agreement (BAA) that covers SES as a service, but the BAA does not protect Protected Health Information (PHI) in the body of the mail once it leaves AWS. SES TLS enforcement defaults to opportunistic (TlsPolicy: OPTIONAL), so messages silently fall back to plaintext when the recipient server doesn’t advertise STARTTLS — the customer carries the encryption-in-transit obligation.
Paubox closes that gap with always-on TLS, an automatic Secure Portal fallback when the recipient cannot accept encrypted mail, and a BAA signed with every customer. The send-side API is REST/JSON and the migration is straightforward as most patterns map one-to-one.
What stays the same
- REST API over HTTPS with JSON request bodies (when using SESv2; SES v1 form-encoded callers will move to JSON)
- Domain authentication: SPF and DKIM records required
- SMTP as an alternative to the HTTP API
- Webhook-based event notifications for delivery status
- Per-domain sending configuration
Key differences
| Dimension | Amazon SES (SESv2) | Paubox Email API |
|---|---|---|
| Base URL | https://email.{region}.amazonaws.com/v2/email/outbound-emails | https://api.paubox.net/v1/$PAUBOX_ENDPOINT/messages |
| Region selection | Required (us-east-1, eu-west-1, …) | Single global endpoint, no region |
| Auth method | AWS SigV4 (access key + secret + region, or IAM role) | Bearer token — Authorization: Bearer $PAUBOX_API_KEY |
| SDK | @aws-sdk/client-sesv2, boto3 sesv2, Aws::SESV2, etc. | paubox-node, paubox-python3, paubox_ruby, paubox-php, paubox-java, paubox-csharp — or plain fetch / requests |
| Request body shape | Content.Simple.Subject.Data / Body.Html.Data / Destination.ToAddresses[] | data.message.headers.subject / content["text/html"] / recipients[] |
| Attachments | Raw MIME via SendRawEmail only | First-class data.message.attachments[] with base64 content |
| Bulk send | SendBulkEmail (templated only, up to 50 destinations) | /bulk_messages endpoint, recommended max 50 per request |
| Templates | SES templates (CreateTemplate API, Handlebars-style syntax) | Paubox Dynamic Templates (/dynamic_templates CRUD, Handlebars) |
| SMTP host | email-smtp.{region}.amazonaws.com | smtp.paubox.com |
| SMTP credentials | IAM-user-derived SMTP username + password (separate from the AWS API key) | Literal string apikey as username, Paubox API key as password |
| SMTP port | 25, 465, 587, or 2587 | 587 (also supports 465, 25) |
| TLS enforcement | TlsPolicy: OPTIONAL | REQUIRE (per configuration set) | Always-on, cannot be disabled |
| Delivery feedback | SNS topic subscription → HTTPS endpoint | Paubox webhooks (HTTPS POST directly to your endpoint) |
| Message ID returned | MessageId | sourceTrackingId |
Send a single email
Note:
$PAUBOX_ENDPOINT is the username shown on your Paubox Email API > Settings page — not your email address.Note:SES uses AWS SigV4 over the AWS credential chain (
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, or an IAM role). Paubox uses a single Bearer token. After cutover, remove the AWS SDK dependency and any AWS credentials scoped to ses:SendEmail from your runtime environment.SMTP configuration
Webhook event mapping
SES does not push HTTP webhooks directly — bounces, complaints, and deliveries are published to an SNS topic that fans out to an HTTPS subscription. Paubox replaces both layers with a direct HTTPS POST to your endpoint.| SES SNS event | Paubox event key | Notes |
|---|---|---|
Delivery | api_mail_log_delivered | |
Open | api_mail_log_opened | |
Bounce (bounceType: Permanent) | api_mail_log_permanent_failure | |
Bounce (bounceType: Transient) | api_mail_log_temporary_failure | |
Click | — no equivalent | Poll click data via Get message receipt |
Complaint | — no equivalent | Manage unsubscribes in the Paubox dashboard |
Reject | — no equivalent | Paubox returns rejections synchronously in the POST response, not as a webhook |
Send | — no equivalent | delivered confirms acceptance; remove handler |
Note:Click tracking is available by polling
GET /message_receipt?sourceTrackingId=... — it is not delivered as a push webhook event.Note:Paubox webhooks POST directly to your HTTPS endpoint. There is no intermediary SNS topic, so the JSON envelope is flatter than the SES → SNS → subscription payload. Configure endpoints in the Paubox dashboard under Email API → Webhooks. See the Webhooks reference for the payload shape.
Template migration
If you use SES templates (CreateTemplate / SendTemplatedEmail / SendBulkTemplatedEmail), recreate each one as a Paubox Dynamic Template. Both systems use Handlebars-style {{variable}} syntax, so most template bodies port verbatim.
Export each SES template
Run
aws ses get-template --template-name <name> (or aws sesv2 get-email-template) and capture the Subject, HtmlPart, and TextPart fields.Create the Paubox Dynamic Template
POST each template to
/dynamic_templates with the body remapped to Paubox’s shape. See the Dynamic templates reference for the request format.Migration checklist
Sign a BAA with Paubox
Required before go-live. Contact Paubox to initiate the Business Associate Agreement.
Create an account and verify your sending domain
Add your domain on the Paubox Email API > Settings page and complete the TXT record verification. See the Quickstart guide for step-by-step instructions.
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).Replace the AWS SDK call with a Paubox request
Remove
@aws-sdk/client-ses / @aws-sdk/client-sesv2 (or the boto3 / Aws::SESV2 equivalent) and call Paubox via fetch / one of the Paubox SDKs. Restructure the request body to use the data.message shape shown above.Remove AWS credentials from runtime config
Drop
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, and any IAM role permissions scoped to ses:SendEmail / ses:SendRawEmail / ses:SendBulkEmail.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. Delete the IAM user that was created for SES SMTP credentials.Recreate SES templates as Paubox Dynamic Templates
See Template migration above.
Tear down the SNS topic and HTTPS subscription
Remap your bounce / complaint / delivery handler to the Paubox webhook payload using the event mapping table above, then delete the SNS topic and configuration-set event destination used for SES feedback.
Remove any TLS policy overrides
Paubox enforces TLS unconditionally — remove
TlsPolicy: OPTIONAL or TlsPolicy: REQUIRE from any SES configuration set you were referencing.Send a test message
Confirm delivery using the Get message receipt endpoint with the
sourceTrackingId returned from your test send.Swap DNS records
Replace SES SPF and DKIM records with the Paubox records shown in your Settings page.
Next steps
Quickstart guide
Full setup walkthrough from account creation to first send
Webhooks reference
Configure delivery event notifications
Batch send
Send up to 50 messages in a single request
SMTP API
Connect via SMTP instead of REST