Migrate from Amazon SES
The provider-specific half of the migration guide: how the SES v2 SendEmail call, account-level suppression list, and SNS-based event notifications map onto Bird. Do the steps in the main guide in order; this page is the lookup table for steps 1, 3, and 4.
Map the send call
SES splits a send across Destination, Content, and configuration-set plumbing; Bird's POST /v1/email/messages is one flat payload:
| What it does | SES (SendEmail v2) | Bird |
|---|---|---|
| Sender | FromEmailAddress | from |
| Recipients | Destination.*Addresses | to / cc / bcc (arrays) |
| Subject | Content.Simple.Subject | subject |
| Body | Content.Simple.Body.Html/Text | html / text (at least one) |
| Reply-to | ReplyToAddresses | reply_to (array) |
| Custom headers | Content.Simple.Headers | headers (string → string object) |
| Filterable labels | EmailTags | tags: {name, value} pairs |
| Round-trip context | (none) | metadata: arbitrary JSON |
| Stored template | Content.Template | template + template.parameters |
| Open/click tracking | configuration set | track_opens / track_clicks (default true) |
| IP pool | dedicated IP pool (config set) | ip_pool_id (ipp_... or ipp_shared) |
| Category | (none) | category: marketing (default) or transactional |
Bird-side field caps and defaults (recipient counts, tag and metadata limits) live in Sending email.
Porting notes:
- Configuration sets dissolve into per-message fields. Tracking, IP pool, and event routing were configuration-set concerns on SES; on Bird the first two are payload fields and event routing is a webhook subscription.
- Auth changes from SigV4 to a bearer token. No request signing; a plain Authorization: Bearer bk_... header. Drop the AWS SDK credential chain from this code path.
- SES templates port to stored templates, with one caveat. Content.Template (template name plus TemplateData) maps to Bird's template field with values in template.parameters; see sending with a template. Template authoring on Bird is in preview and not yet open to every workspace, so until yours has it, render content in your application and send html/text.
- Content.Raw (MIME) has no equivalent. Bird builds the message from structured fields. If you assemble raw MIME to attach files, send them as Bird's attachments array instead (base64 content per file, content_id for inline images).
- SES sandbox ≠ Bird sandbox. SES's sandbox restricts who you can send to; Bird's mail sandbox is a simulator with magic addresses: no allowlisting, and nothing is delivered.
Export suppressions
Export the account-level suppression list and run it through the import loop:
- GET /v2/email/suppressed-destinations (paginate with NextToken; each entry carries BOUNCE or COMPLAINT as the reason)
Translate webhook events
SES publishes events through SNS or EventBridge; Bird POSTs signed webhooks directly, so the SNS topic, subscription-confirmation handshake, and message-envelope unwrapping all go away. The event names map like this:
| Outcome | SES | Bird |
|---|---|---|
| Accepted/processed | Send | email.accepted → email.processed |
| Delivered | Delivery | email.delivered |
| Temporary failure | DeliveryDelay | email.deferred |
| Permanent bounce | Bounce | email.bounced / email.out_of_band_bounce |
| Spam complaint | Complaint | email.complained |
| Blocked/suppressed | (none) | email.rejected |
| Open | Open | email.opened |
| Click | Click | email.clicked |
| Unsubscribe | Subscription | email.list_unsubscribed |
email.rejected is new relative to SES: Bird reports suppressed recipients visibly (status rejected, rejection_reason: recipient_suppressed) rather than counting them into the send-and-bounce cycle. Add a handler for it.
In place of SNS message verification, Bird signs per the Standard Webhooks specification, with HMAC headers on the delivery itself; the verification recipe is in Webhooks & events.
Cut over
Work through domains & DNS and the sandbox smoke test in the main guide; both are provider-independent. One SES-specific note for the DNS step: SES's "Easy DKIM" CNAMEs stay in place during the transition. Bird's DKIM TXT record uses its own selector, so the two coexist.
Next steps
- Sending domains: registration, verification lifecycle, and the DNS records you're re-pointing
- Webhooks & events: endpoint setup and Standard Webhooks verification
- Testing sandbox: smoke-test the new integration before cutover
- Suppressions: confirm your imported list and how Bird maintains it from here