Documentation
Sign inGet started

Migrate from SendGrid

The provider-specific half of the migration guide: how SendGrid's v3 Mail Send payload, suppression lists, and Event Webhook 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

SendGrid's POST /v3/mail/send wraps recipients in a personalizations array; Bird's POST /v1/email/messages is a flat payload, so each personalization becomes its own send (or one batch entry).
What it doesSendGridBird
Senderfrom.emailfrom
Recipientspersonalizations[].to / cc / bccto / cc / bcc (arrays)
Subjectsubjectsubject
Bodycontent[] (type + value)html / text (at least one)
Reply-toreply_to / reply_to_listreply_to (array)
Custom headersheadersheaders (string → string object)
Filterable labelscategoriestags: {name, value} pairs
Round-trip contextcustom_argsmetadata: arbitrary JSON
Stored templatetemplate_id + dynamic_template_datatemplate + template.parameters
Schedulingsend_atscheduled_at
Open/click trackingtracking_settingstrack_opens / track_clicks (default true)
IP poolip_pool_nameip_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:
  • categories are bare strings; Bird tags are pairs. A category like "welcome" becomes {"name": "category", "value": "welcome"}. Pick a stable name so your dashboards filter the way your SendGrid stats did.
  • custom_args were echoed in every event; Bird metadata works the same way. Bird echoes your metadata (and tags) on every webhook event alongside email_id/recipient_id, so your handlers get your context back without an extra lookup.
  • Dynamic templates port to stored templates. template_id plus dynamic_template_data become template (referenced by ID or name) plus template.parameters on the same send call; 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. send_at maps to scheduled_at directly.
  • Attachments port directly. SendGrid's attachments (base64 content, type, filename, content_id for inline) map to Bird's attachments array field-for-field.
  • Unsubscribe groups (asm) don't port as a concept: Bird handles list-unsubscribe at the category level, so marketing mail gets suppression-aware unsubscribe handling automatically.

Export suppressions

SendGrid splits suppressions across endpoints; export each and run them through the import loop:
  • GET /v3/suppression/bounces
  • GET /v3/suppression/spam_reports
  • GET /v3/suppression/unsubscribes (global unsubscribes)
  • GET /v3/asm/groups/{group_id}/suppressions for each unsubscribe group you want to carry over

Translate webhook events

OutcomeSendGrid Event WebhookBird
Accepted/processedprocessedemail.acceptedemail.processed
Delivereddeliveredemail.delivered
Temporary failuredeferredemail.deferred
Permanent bouncebounceemail.bounced / email.out_of_band_bounce
Spam complaintspamreportemail.complained
Blocked/suppresseddroppedemail.rejected
Openopenemail.opened
Clickclickemail.clicked
Unsubscribeunsubscribe / group_unsubscribeemail.unsubscribed / email.list_unsubscribed
The droppedemail.rejected equivalence is the one to test: like SendGrid, Bird reports suppressed recipients visibly (status rejected, rejection_reason: recipient_suppressed) rather than silently dropping them, so your audit logic ports cleanly.
Verification changes more than the event names: SendGrid's Event Webhook signs with an ECDSA public key, while Bird signs per the Standard Webhooks HMAC scheme. Swap your verification code for the recipe in Webhooks & events. SendGrid also batches events into JSON arrays; Bird delivers one event per request.

Cut over

Work through domains & DNS and the sandbox smoke test in the main guide; both are provider-independent.

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