# Migreren vanuit Brevo

Deze pagina vertaalt de transactionele verzendpayload, blokkeerlijsten en webhooks van Brevo naar Bird. Volg de [hoofdmigratiegids](/docs/guides/email/migrate) op volgorde en gebruik deze vertalingen voor stap 1, 3 en 4.

Brevo bewaart suppressies op twee losstaande plekken, één voor transactionele mail en één voor marketing. Lees [Suppressies exporteren](#suppressies-exporteren) voordat je stap 3 plant: slechts één van de twee exporteren is de fout waar deze migratie toe uitnodigt.

## Geef dit aan je agent

Plak dit in Claude Code, Cursor of Codex. De agent werkt deze pagina door tegen je eigen repository, via het Bird-oppervlak dat hij al heeft: de MCP-server als er één verbonden is, de CLI als die geïnstalleerd en ingelogd is.

```text
I am moving an email integration from Brevo to Bird. Route through it with me.
1. Check what you already have before setting anything up. If Bird's MCP server is connected, use its tools. If the Bird CLI is installed and signed in, use that. Either one is enough, and every step below is an action you take with whichever you have. Only if neither is present, follow https://bird.com/docs/ai/set-up-your-agent.md to set one up and sign me in. Every Bird docs page serves Markdown at its own URL with `.md` appended, so fetch that rather than the HTML.
2. Read https://bird.com/docs/guides/email/migrate/brevo.md for the payload, suppression and webhook mapping, and https://bird.com/docs/guides/email/migrate.md for the order the steps go in.
3. Find and list my Brevo usage in this repository before you change anything: calls to /v3/smtp/email and any SDK wrappers around them, whether I send with templateId or with htmlContent, the webhook handler and the URL it is registered at, and every domain I send from. Tell me the list before you edit anything.
4. Register each of those sending domains with Bird and give me the DNS records to publish, following https://bird.com/docs/guides/email/sending-domains.md. Leave every DNS record Brevo uses exactly as it is: Bird's records are published alongside them and both providers authenticate side by side until I switch traffic. Publishing DNS affects mail for the whole domain, so show me the records and let me publish them.
5. Export my suppressions and import them into Bird before any production traffic goes through Bird, so my first sends do not reach addresses that already bounced or complained. Brevo holds these in two separate places and I need both: GET /v3/smtp/blockedContacts for transactional blocks and unsubscribes, and the marketing blocklist, which lives on the contact records as emailBlacklisted rather than on a suppression endpoint. Page through both. The Bird import takes one address per request and is idempotent, so a partial re-run is safe. https://bird.com/docs/guides/email/suppressions.md has the reason taxonomy.
6. Port the send call and the webhook handler using the mapping tables on the provider page. Brevo's webhook security page documents credentials I configure on the endpoint rather than a payload signature, so check what my endpoint actually relies on today: if it is a username and password in the webhook URL, take them out and tell me to rotate that pair rather than reusing it, because a credential that has lived in a URL should be treated as exposed. Bird signs every delivery instead. https://bird.com/docs/guides/webhooks.md and https://bird.com/docs/guides/email/events.md.
7. Run my whole integration against Bird's mail sandbox before any production traffic, following https://bird.com/docs/guides/email/testing-sandbox.md. Sandbox sends run the real pipeline without reaching an inbox or touching my sending reputation.
8. Stop and ask me wherever a step needs a decision. Do not point production traffic at Bird until I have seen the sandbox results and replied with the words cut over to Bird. Retiring the Brevo path is a separate step that comes later: ask me again and wait for me to reply with the words retire the Brevo path. A reply that agrees without naming what it is authorising is not authorisation. Finish by telling me what is left that only a person can do.
```

## Vertaal de verzendaanroep

`POST /v3/smtp/email` van Brevo en onze [`POST /v1/email/messages`](/docs/api/reference/create-email-message) lijken qua structuur sterk op elkaar. Het meeste werk is het uitpakken van Brevo's adresobjecten naar platte strings.

| Functie             | Brevo                                            | Bird                                                                       |
| ------------------- | ------------------------------------------------ | -------------------------------------------------------------------------- |
| Auth                | `api-key`-header                                 | `Authorization: Bearer`                                                    |
| Afzender            | `sender` (`{email, name}`)                       | `from`                                                                     |
| Ontvangers          | `to` / `cc` / `bcc` (arrays van `{email, name}`) | `to` / `cc` / `bcc` (arrays van adressen)                                  |
| Onderwerp           | `subject`                                        | `subject`                                                                  |
| Body                | `htmlContent` / `textContent`                    | `html` / `text` (minstens één)                                             |
| Reply-to            | `replyTo` (`{email, name}`)                      | `reply_to` (array)                                                         |
| Aangepaste headers  | `headers` (Title-Case keys)                      | `headers` (string → string object)                                         |
| Filterbare labels   | `tags` (array van strings)                       | `tags`: `{name, value}`-paren                                              |
| Opgeslagen template | `templateId` + `params`                          | `template` + `template.parameters`                                         |
| Bijlagen            | `attachment` (`url` of base64 `content`)         | `attachments` (alleen base64, zie hieronder)                               |
| Planning            | `scheduledAt`                                    | `scheduled_at`                                                             |
| Batchhandle         | `batchId`                                        | (geen tegenhanger, zie hieronder)                                          |
| Kopie per ontvanger | `messageVersions`                                | één verzending per versie, of een [batch](/docs/guides/email/sending-bulk) |
| Categorie           | (geen)                                           | `category`: `marketing` (standaard) of `transactional`                     |

Onze veldlimieten en standaardwaarden (aantal ontvangers, tag- en metadatalimieten) staan in [E-mail verzenden](/docs/guides/email/sending-email).

Opmerkingen bij het overzetten:

- **Adressen zijn daar objecten en hier strings.** `{"email": "a@x.com", "name": "A"}` wordt `"A <a@x.com>"` of gewoon `"a@x.com"`. Hetzelfde uitpakken geldt voor `sender` en `replyTo`.
- **`tags` zijn kale strings. Onze tags zijn paren.** Een tag zoals `"welcome"` wordt `{"name": "category", "value": "welcome"}`. Kies een stabiele `name` zodat je dashboards filteren zoals je Brevo-tagstatistieken deden.
- **`params` is templatedata, geen round-tripcontext.** Het wordt `template.parameters`. Als je het ook gebruikte om eigen identifiers door te geven aan events, verplaats die dan naar [`metadata`](/docs/guides/email/sending-email), dat we bij elk webhookevent teruggeven naast `email_id`/`recipient_id`.
- **`messageVersions` heeft geen equivalent in één aanroep.** Elke versie is een aparte set ontvangers en payload, dus het wordt ofwel een eigen verzending ofwel één item in een [batch](/docs/guides/email/sending-bulk).
- **`batchId` heeft geen tegenhanger.** `batchId` van Brevo groepeert geplande berichten zodat je ze als set kunt annuleren of opnieuw plannen. Geplande verzendingen worden hier individueel aangesproken via hun bericht-id; er is geen groepshandle om mee te geven of tegen te annuleren.
- **Bijlage via URL wordt niet ondersteund.** Brevo accepteert een `attachment`-item als URL die het zelf ophaalt. Haal het bestand zelf op en stuur het base64-gecodeerd mee; zie [bijlagen](/docs/guides/email/attachments).

## Suppressies exporteren

Brevo verdeelt suppressies over twee systemen die geen endpoint of paginatieschema delen, en een migratie die alleen het eerste ophaalt, verliest stilletjes elke marketing-uitschrijving:

- **Transactionele blokkeringen en uitschrijvingen**: `GET /v3/smtp/blockedContacts`, gepagineerd (standaard 50 per pagina, maximaal 100), elk item met de reden van blokkering.
- **Marketingblokkeerlijst**: helemaal geen suppressie-endpoint. Het staat op het contactrecord als `emailBlacklisted`, dus pagineer `GET /v3/contacts` (maximaal 1000 per pagina met `offset`) en bewaar de contacten waar die vlag true is.

Voer beide door de [importlus](/docs/guides/email/migrate#3-import-suppressions). De blokkeringsredenen van Brevo komen overeen met onze `hard_bounce`-, `complaint`- en `manual`-redenen; [Suppressies](/docs/guides/email/suppressions) bevat de volledige taxonomie.

## Webhookevents vertalen

| Uitkomst               | Brevo                       | Bird                                             |
| ---------------------- | --------------------------- | ------------------------------------------------ |
| Geaccepteerd/verwerkt  | `request`                   | `email.accepted` → `email.processed`             |
| Afgeleverd             | `delivered`                 | `email.delivered`                                |
| Tijdelijke fout        | `deferred` / `soft_bounce`  | `email.deferred`                                 |
| Permanente bounce      | `hard_bounce`               | `email.bounced` / `email.out_of_band_bounce`     |
| Spamklacht             | `spam`                      | `email.complained`                               |
| Geblokkeerd/onderdrukt | `blocked` / `invalid_email` | `email.rejected`                                 |
| Open                   | `opened` / `unique_opened`  | `email.opened`                                   |
| Klik                   | `click`                     | `email.clicked`                                  |
| Uitschrijving          | `unsubscribed`              | `email.unsubscribed` / `email.list_unsubscribed` |

Twee verschillen bepalen hoeveel er aan je handler verandert.

**Controleer waar je endpoint nu op vertrouwt voordat je het overzet.** De webhookbeveiligingspagina van Brevo beschrijft credentials die je op het endpoint configureert: een gebruikersnaam en wachtwoord achter de URL als `https://username:password@example.com/`, een bearer-token, aangepaste requestheaders en IP-ranges. Wij ondertekenen elke aflevering volgens het [Standard Webhooks](https://www.standardwebhooks.com) HMAC-schema, dus verificatie verschuift van iets dat de aanroeper meestuurt naar iets dat je handler berekent. Als je huidige endpoint credentials in de URL heeft, haal ze eruit en roteer dat paar in plaats van het te hergebruiken: een credential die in een URL heeft gestaan, is terechtgekomen in access logs, configuratie-exports en een leveranciersconsole. Het recept staat in [Webhooks en events](/docs/guides/webhooks).

**Brevo onderscheidt opens en kliks van hun unieke varianten. Wij niet.** `opened` en `unique_opened` komen allebei binnen als `email.opened`, dus een handler die alleen de unieke variant telde, moet nu zelf dedupliceren op `recipient_id`. Onze afleveringsevents zijn per ontvanger, dus een verzending naar drie ontvangers levert drie afleveringsuitkomsten op in plaats van één.

## Omschakelen

Werk [domeinen en DNS](/docs/guides/email/migrate#2-re-point-domains-and-dns) en de [sandbox-rooktest](/docs/guides/email/migrate#5-verify-in-the-sandbox-before-cutover) in de hoofdgids door. Beide zijn provideronafhankelijk.

## Vervolgstappen

- [Verzenddomeinen](/docs/guides/email/sending-domains): registratie, verificatielevenscyclus en de DNS-records die je publiceert
- [Webhooks en events](/docs/guides/webhooks): endpointconfiguratie en Standard Webhooks-verificatie
- [Testsandbox](/docs/guides/email/testing-sandbox): rooktest van de nieuwe integratie vóór de omschakeling
- [Suppressies](/docs/guides/email/suppressions): controleer je geïmporteerde lijst en hoe we die vanaf hier onderhouden

## Related resources

- [Getting started with email](/learn/email/getting-started-with-email) (video)
- [Email](/products/email) (product)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first email](/docs/get-started/send-your-first-email) (docs)

[Get an implementation brief](/learn/workspace?topic=email)
