Documentation
Sign inGet started

Migrate from another provider

This guide walks you through moving production email to Bird. The shape of the work is the same regardless of where you're coming from: one send endpoint to re-map, four DNS records to publish, a suppression list to carry over, a webhook vocabulary to translate, and a sandbox to verify everything against before you flip traffic.
The migration checklist:
  1. Map your send call to POST /v1/email/messages
  2. Re-point your sending domains and DNS
  3. Import your suppression list
  4. Switch webhooks to Bird's event vocabulary
  5. Verify against the mail sandbox before cutover
Steps 1, 3, and 4 depend on which provider you're leaving. Each provider guide carries the field-by-field payload mapping, where to export your suppression list, and the webhook event-name translation table:

1. Map the send call

Bird has one single-send endpoint, POST /v1/email/messages. You build a flat JSON payload — no personalizations wrapper, no MIME assembly — with from, to/cc/bcc (up to 50 each), subject, html and/or text, optional reply_to (an array, 1–25 entries), and headers for custom email headers. A successful send returns 202 Accepted with an em_-prefixed message ID; delivery outcomes arrive asynchronously through webhooks and the read endpoints. The full payload reference is in Sending email; the field-by-field mapping from your current payload is in your provider guide.
The distinction between tags and metadata matters more on Bird than the equivalents did at your old provider: tags are first-class filter dimensions (message list, analytics, dashboard rollups), while metadata is opaque round-trip context stored on the message and read back via the API (webhook payloads carry the correlation IDs, not your metadata — fetch the message by email_id to recover it). The rule of thumb and limits are in Tags vs metadata.
Bird differences worth flagging before you port code:
  • Some fields are reserved, not yet available. attachments, scheduled_at, and template (along with a few other names) are part of the request vocabulary but return 422 unsupported_feature today — if your current integration sends attachments, schedules sends, or renders provider-hosted templates, plan around that before cutover. The full reserved list is in Sending email.
  • Suppressed recipients are rejected, visibly. A suppressed address still gets a recipient_id and appears in the message's recipient list with status rejected and an email.rejected event (rejection_reason: recipient_suppressed) — never a silent drop. If every recipient is suppressed, the whole request fails with 422 all_recipients_suppressed. See Suppressions.
  • Set category explicitly for marketing mail. The default is transactional regardless of content, and the category controls suppression policy: marketing blocks on complaints and unsubscribes, transactional delivers through them. If you're migrating newsletters or campaigns, send them with category: "marketing" — don't rely on the default.

2. Re-point domains and DNS

Register each sending domain with POST /v1/email/domains or in the dashboard, then publish the records from the response's dns_records array. Bird asks for four records — and notably not the one most providers make you start with:
RecordTypeGates sending
DKIMTXTYes — per-organization selector and key, generated for you
Return-pathCNAMEYes — routes bounces to Bird and provides SPF alignment
DMARCTXTYes — any valid policy; an existing record (or one at a parent domain) already counts
TrackingCNAMENo — only gates branded open/click tracking
The send gate is DKIM + return-path + DMARC. There is no SPF record to publish at your domain apex: SPF is evaluated against the envelope-from domain, which the return-path CNAME points at Bird's bounce infrastructure, so SPF passes and aligns without touching your apex. If your old provider had you add an include: to your apex SPF record, you can leave it in place during the transition and remove it after cutover — it neither helps nor hurts your Bird mail, and removing it frees one of the 10 DNS lookups apex SPF allows. The full explanation is in DKIM, SPF & DMARC.
Verification is automatic — Bird polls your DNS starting within seconds of registration, and most domains verify within minutes of the records propagating. Each Bird region (us1, eu1) is independent, so register the domain in every region you send from. Domain lifecycle details are in Sending domains.
You can publish Bird's records while your old provider's records are still live: the DKIM record uses a Bird-specific selector, the return-path and tracking CNAMEs are new hostnames you choose, and your existing DMARC record satisfies the gate as-is — so both providers authenticate side by side until you're ready to switch traffic.

3. Import suppressions

Carry your suppression list over before sending production traffic through Bird — otherwise your first sends go to addresses that already bounced or complained at your old provider, which damages the reputation you're trying to protect.
Export the list from your current provider (your provider guide has the exact endpoints), then add each address to Bird with POST /v1/email/suppressions:
Codevoorbeeld
while read -r address; do
  curl -s -X POST https://us1.platform.bird.com/v1/email/suppressions \
    -H "Authorization: Bearer $BIRD_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"email\": \"$address\"}"
done < suppressions.txt
Two things to know about this import path:
  • There is no bulk-import endpoint yet. The v1 suppressions API is single-entry CRUD — one address per POST — so importing a large list means looping, as above. Bulk import is deferred to a later release; until then, the loop is the supported path. The call is idempotent (201 for a new record, 200 with the existing record if the address is already manually suppressed), so re-running a partial import is safe.
  • Imported addresses get reason: manual, applies_to: all — they block every category, including transactional. That is stricter than a complaint or unsubscribe record would be natively (those block only non-transactional sends), so if you need the category-aware behavior for specific addresses, see the reason taxonomy in Suppressions.
Going forward you don't manage bounces yourself: Bird auto-suppresses hard bounces, complaints, and unsubscribes, and fires email_suppression.created so your systems can mirror the list.

4. Switch webhooks

Register an endpoint with POST /v1/webhooks and subscribe it to an explicit list of event types. Bird's event names follow resource.actionemail.acceptedemail.processedemail.delivered on the happy path, with email.deferred, email.bounced, email.complained, email.rejected, email.opened, email.clicked, and the unsubscribe pair covering the rest. The event-name translation from your current provider's vocabulary is in your provider guide; per-event payload schemas are in the events reference.
Every webhook payload carries the correlation IDs — email_id, recipient_id, and workspace_id — so you can tie any event back to your send; tags and metadata are not echoed in the payload. If your current handler relies on payload echo for correlation, the pattern ports to Bird as: store your context in metadata on the send, then read it back with GET /v1/email/messages/{email_id} when an event needs it — payload echo becomes an API lookup.
Bird signs deliveries per the Standard Webhooks specification — webhook-id, webhook-timestamp, and webhook-signature headers with an HMAC-SHA256 over {id}.{timestamp}.{raw body}. If you already verify Standard Webhooks deliveries from another platform, the exact same verification code works for Bird; otherwise the verification recipe, retry schedule, and replay tooling are in Webhooks & events. Deliveries are at-least-once and unordered, so deduplicate on webhook-id and sort by the payload timestamp — the same discipline your current handler should already have.

5. Verify in the sandbox before cutover

Before you move production traffic, run your full integration — the ported send call, your webhook handler, your suppression mirroring — against the mail sandbox. Sandbox sends go to magic addresses at messagebird.dev and run through the real production pipeline (same 202, same event sequence, same signed webhook deliveries) without ever reaching an inbox or touching your reputation.
A minimal pre-cutover smoke test:
  1. Send to delivered@messagebird.dev and assert your handler processes email.acceptedemail.processedemail.delivered.
  2. Send to bounce@messagebird.dev and assert your bounce handling fires on email.bounced (simulated bounces don't write to your suppression list, so the address stays reusable).
  3. Send to suppressed@messagebird.dev and assert you handle a lone email.rejected — the shape every suppressed recipient produces in production (the rejection_reason: recipient_suppressed detail is on the recipient record and the events API).
  4. Send a category: "marketing" message and confirm the category shows up where you expect in events and reads.
Use +label subaddressing (bounce+cutover-test@messagebird.dev) to correlate test cases — the full address appears in your events. Once the smoke test passes, cut traffic over: point your application at Bird, keep the old provider's DNS in place until your Bird domains show capabilities.sending verified, and watch the first hours of real deliveries in the dashboard and your webhook stream.

Migrating from a specific provider

  • SendGridpersonalizations → flat payload, categories/custom_argstags/metadata, the droppedemail.rejected equivalence
  • Mailguno:*/v:*/h:* parameters → first-class fields, bounces/complaints/unsubscribes export
  • Amazon SES — SendEmail v2 → one endpoint, configuration sets → per-message tracking flags, SNS → signed webhooks
  • Resend — near-identical payload shape, Svix-signed webhooks → Standard Webhooks
  • Sending email — the full send payload, tags vs metadata, the async 202 model
  • Sending domains — registration, verification lifecycle, multi-region setup
  • DKIM, SPF & DMARC — what each record proves, and why apex SPF isn't required
  • Suppressions — reasons, categories, and the management API
  • Webhooks & events — endpoint setup, Standard Webhooks verification, retries and replay
  • Events — per-event payload schemas
  • Testing sandbox — the full magic-address list and walkthroughs
  • API reference — request and response schemas for the send endpoint