Migrate from Mailjet
The provider-specific half of the migration guide: how Mailjet's Send API v3.1 payload, blocklist, and Event API map onto Bird. Do the steps in the main guide in order — this page is the lookup table for steps 1, 3, and 4.
The biggest structural change is the envelope. Mailjet wraps every send in a Messages array of PascalCase objects (POST /v3.1/send); Bird takes one flat, lowercase JSON object per POST /v1/email/messages, and many independent messages go to the batch endpoint instead of the Messages array.
Map the send call
| What it does | Mailjet (Send API v3.1) | Bird |
|---|---|---|
| Sender | From — { "Email", "Name" } | from — string or { "email", "name" } |
| Recipients | To / Cc / Bcc — [{ "Email", "Name" }] | to / cc / bcc — arrays, max 50 each |
| Subject | Subject | subject |
| Body | TextPart / HTMLPart | text / html (at least one) |
| Reply-to | ReplyTo — { "Email", "Name" } | reply_to — array, 1–25 |
| Custom headers | Headers | headers — string → string object |
| Round-trip context | EventPayload (string), echoed on events | metadata — arbitrary JSON, max 2 KB |
| Your own send ID | CustomID | Idempotency-Key header + tags/metadata |
| Attachments | Attachments — { "ContentType", "Filename", "Base64Content" } | attachments — { "content_type", "filename", "content" } |
| Inline images | InlinedAttachments — with ContentID | attachments with content_id |
| Tracking | account/template setting | track_opens / track_clicks (default true) |
| Category | — | category: transactional (default) or marketing |
Porting notes:
- Unwrap the Messages array. A single Mailjet send is one entry in Messages; on Bird that's the whole request body. If you batch several entries in one Messages array, that maps to Bird's batch endpoint (up to 100 messages), not to repeated fields in one request.
- Case changes from PascalCase to lowercase. Every field renames: HTMLPart → html, TextPart → text, From.Email → from.email. This is mechanical but touches every send.
- EventPayload becomes metadata. Mailjet echoes a single EventPayload string back on every event; Bird echoes structured metadata (JSON) and tags on every webhook, so you can split correlation data into typed fields. See tags vs metadata.
- CustomID splits in two. Mailjet's CustomID does double duty as a dedup key and a correlation handle. On Bird, use the Idempotency-Key header for safe retries and put your own correlation ID in metadata.
- Templates render in your app. Mailjet's TemplateID + Variables (server-hosted templates with TemplateLanguage) have no Bird equivalent yet — template_id is reserved. Render your template to HTML before sending and pass it as html.
- Attachments port directly — Mailjet's Base64Content is Bird's base64 content, and InlinedAttachments + ContentID become attachments entries with content_id. See attachments.
Export suppressions
Mailjet keeps unreachable and unwanted addresses on its blocklist (hard/soft bounces and blocked sends) and tracks spam and unsubscribe signals separately. Export the blocked and bounced addresses from Statistics → Contacts, or pull them through the contact management API, and run the list through the import loop. If you send marketing mail, also carry over contacts marked unsubscribed so those preferences survive the move.
Translate webhook events
Mailjet's Event API posts one trigger per event type. The mapping to Bird's event vocabulary:
| Outcome | Mailjet | Bird |
|---|---|---|
| Sent / accepted | sent | email.accepted → email.processed |
| Delivered | — | email.delivered |
| Permanent bounce | bounce | email.bounced / email.out_of_band_bounce |
| Blocked | blocked | email.rejected |
| Spam complaint | spam | email.complained |
| Open | open | email.opened |
| Click | click | email.clicked |
| Unsubscribe | unsub | email.unsubscribed / email.list_unsubscribed |
Two differences worth coding for:
- Bird reports delivery explicitly. Mailjet's sent event means the message left Mailjet; Bird splits acceptance (email.accepted/email.processed) from the recipient mail server actually taking the message (email.delivered), so you get a distinct delivered signal.
- Events are recipient-scoped. Mailjet keys events by MessageID; Bird's delivery events carry recipient_id alongside email_id, so a multi-recipient send produces one event stream per recipient. Bird signs deliveries per the Standard Webhooks spec — see Webhooks & events for verification.
Cut over
Work through domains & DNS and the sandbox smoke test in the main guide — both are provider-independent.