# Migration von Brevo

Diese Seite ordnet Brevos transaktionales Send-Payload, Blocklisten und Webhooks Bird zu. Folgen Sie dem [Hauptleitfaden zur Migration](/docs/guides/email/migrate) der Reihe nach und nutzen Sie diese Zuordnungen für die Schritte 1, 3 und 4.

Brevo speichert Suppressions an zwei voneinander unabhängigen Stellen, eine für transaktionale E-Mails und eine für Marketing. Lesen Sie [Suppressions exportieren](#suppressions-exportieren), bevor Sie Schritt 3 planen: Nur eine der beiden Quellen zu exportieren ist der Fehler, den diese Migration provoziert.

## Übergeben Sie dies Ihrem Agenten

Fügen Sie dies in Claude Code, Cursor oder Codex ein. Der Agent arbeitet diese Seite gegen Ihr eigenes Repository ab und nutzt dafür die Bird-Oberfläche, die er bereits hat: den MCP-Server, falls einer verbunden ist, oder die CLI, falls sie installiert und angemeldet ist.

```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.
```

## Send-Aufruf zuordnen

Brevos `POST /v3/smtp/email` und unser [`POST /v1/email/messages`](/docs/api/reference/create-email-message) sind in der Struktur ähnlich. Der Großteil der Arbeit besteht darin, Brevos Adressobjekte in einfache Strings umzuwandeln.

| Funktion               | Brevo                                            | Bird                                                                   |
| ---------------------- | ------------------------------------------------ | ---------------------------------------------------------------------- |
| Auth                   | `api-key`-Header                                 | `Authorization: Bearer`                                                |
| Absender               | `sender` (`{email, name}`)                       | `from`                                                                 |
| Empfänger              | `to` / `cc` / `bcc` (Arrays von `{email, name}`) | `to` / `cc` / `bcc` (Arrays von Adressen)                              |
| Betreff                | `subject`                                        | `subject`                                                              |
| Inhalt                 | `htmlContent` / `textContent`                    | `html` / `text` (mindestens eines)                                     |
| Reply-to               | `replyTo` (`{email, name}`)                      | `reply_to` (Array)                                                     |
| Eigene Header          | `headers` (Title-Case-Schlüssel)                 | `headers` (String-→-String-Objekt)                                     |
| Filterbare Labels      | `tags` (Array von Strings)                       | `tags`: `{name, value}`-Paare                                          |
| Gespeichertes Template | `templateId` + `params`                          | `template` + `template.parameters`                                     |
| Anhänge                | `attachment` (`url` oder Base64 `content`)       | `attachments` (nur Base64, siehe unten)                                |
| Zeitplanung            | `scheduledAt`                                    | `scheduled_at`                                                         |
| Batch-Handle           | `batchId`                                        | (kein Gegenstück, siehe unten)                                         |
| Kopie pro Empfänger    | `messageVersions`                                | ein Send pro Version oder ein [Batch](/docs/guides/email/sending-bulk) |
| Kategorie              | (keine)                                          | `category`: `marketing` (Standard) oder `transactional`                |

Unsere Feldlimits und Standardwerte (Empfängeranzahl, Tag- und Metadaten-Limits) finden Sie unter [E-Mail senden](/docs/guides/email/sending-email).

Portierungshinweise:

- **Adressen sind dort Objekte und hier Strings.** `{"email": "a@x.com", "name": "A"}` wird zu `"A <a@x.com>"` oder einfach `"a@x.com"`. Dasselbe Umwandeln gilt für `sender` und `replyTo`.
- **`tags` sind einfache Strings. Unsere Tags sind Paare.** Ein Tag wie `"welcome"` wird zu `{"name": "category", "value": "welcome"}`. Wählen Sie einen stabilen `name`, damit Ihre Dashboards so filtern wie zuvor Ihre Brevo-Tag-Statistiken.
- **`params` enthält Template-Daten, keinen Round-Trip-Kontext.** Es wird zu `template.parameters`. Falls Sie es auch genutzt haben, um eigene Identifier bis zu den Events durchzureichen, verschieben Sie diese nach [`metadata`](/docs/guides/email/sending-email), das wir bei jedem Webhook-Event zusammen mit `email_id`/`recipient_id` zurückgeben.
- **`messageVersions` hat kein Einzelaufruf-Äquivalent.** Jede Version ist ein eigener Empfängerkreis und Payload, daher wird sie entweder zu einem eigenen Send oder zu einem Eintrag in einem [Batch](/docs/guides/email/sending-bulk).
- **`batchId` hat kein Gegenstück.** Brevos `batchId` gruppiert geplante Nachrichten, damit Sie sie als Einheit stornieren oder neu planen können. Geplante Sends werden hier einzeln über ihre Message-ID adressiert; es gibt kein Gruppen-Handle zum Übergeben oder Stornieren.
- **Anhang per URL wird nicht unterstützt.** Brevo akzeptiert einen `attachment`-Eintrag als URL, die es selbst abruft. Rufen Sie die Datei selbst ab und senden Sie sie Base64-kodiert; siehe [Anhänge](/docs/guides/email/attachments).

## Suppressions exportieren

Brevo verteilt Suppressions auf zwei Systeme, die weder Endpoint noch Paginierungsschema teilen. Eine Migration, die nur das erste abfragt, verliert stillschweigend jede Marketing-Abmeldung:

- **Transaktionale Sperren und Abmeldungen**: `GET /v3/smtp/blockedContacts`, paginiert (standardmäßig 50 pro Seite, maximal 100), jeder Eintrag mit dem Sperrgrund.
- **Marketing-Blockliste**: kein Suppression-Endpoint. Sie liegt auf dem Kontaktdatensatz als `emailBlacklisted`, also paginieren Sie `GET /v3/contacts` (bis zu 1000 pro Seite mit `offset`) und behalten Sie die Kontakte, bei denen dieses Flag true ist.

Lassen Sie beide durch die [Import-Schleife](/docs/guides/email/migrate#3-import-suppressions) laufen. Brevos Sperrgründe werden auf unsere Gründe `hard_bounce`, `complaint` und `manual` abgebildet; [Suppressions](/docs/guides/email/suppressions) enthält die vollständige Taxonomie.

## Webhook-Events übersetzen

| Ergebnis               | Brevo                       | Bird                                             |
| ---------------------- | --------------------------- | ------------------------------------------------ |
| Akzeptiert/verarbeitet | `request`                   | `email.accepted` → `email.processed`             |
| Zugestellt             | `delivered`                 | `email.delivered`                                |
| Temporärer Fehler      | `deferred` / `soft_bounce`  | `email.deferred`                                 |
| Permanenter Bounce     | `hard_bounce`               | `email.bounced` / `email.out_of_band_bounce`     |
| Spam-Beschwerde        | `spam`                      | `email.complained`                               |
| Blockiert/unterdrückt  | `blocked` / `invalid_email` | `email.rejected`                                 |
| Öffnung                | `opened` / `unique_opened`  | `email.opened`                                   |
| Klick                  | `click`                     | `email.clicked`                                  |
| Abmeldung              | `unsubscribed`              | `email.unsubscribed` / `email.list_unsubscribed` |

Zwei Unterschiede bestimmen, wie stark sich Ihr Handler ändert.

**Prüfen Sie, worauf sich Ihr Endpoint heute stützt, bevor Sie ihn portieren.** Brevos Webhook-Sicherheitsseite dokumentiert Credentials, die Sie am Endpoint konfigurieren: einen Benutzernamen und ein Passwort, die als `https://username:password@example.com/` an die URL angehängt werden, ein Bearer-Token, eigene Request-Header und IP-Bereiche. Wir signieren jede Zustellung stattdessen gemäß dem [Standard Webhooks](https://www.standardwebhooks.com)-HMAC-Schema, sodass die Verifizierung von etwas, das der Aufrufer mitbringt, zu etwas wird, das Ihr Handler berechnet. Falls Ihr aktueller Endpoint Credentials in der URL hält, entfernen Sie diese und rotieren Sie das Paar, anstatt es wiederzuverwenden: Ein Credential, das in einer URL gelebt hat, ist in Access-Logs, Config-Exports und einer Anbieter-Konsole gelandet. Die Anleitung finden Sie unter [Webhooks und Events](/docs/guides/webhooks).

**Brevo unterscheidet Öffnungen und Klicks von deren eindeutigen Varianten. Wir nicht.** `opened` und `unique_opened` kommen beide als `email.opened` an, sodass ein Handler, der nur die eindeutige Variante gezählt hat, anhand von `recipient_id` selbst deduplizieren muss. Unsere Delivery-Events sind empfängerbezogen, sodass ein Send an drei Empfänger drei Zustellergebnisse erzeugt statt eines.

## Umstellung

Arbeiten Sie [Domains und DNS](/docs/guides/email/migrate#2-re-point-domains-and-dns) sowie den [Sandbox-Smoke-Test](/docs/guides/email/migrate#5-verify-in-the-sandbox-before-cutover) im Hauptleitfaden durch. Beides ist anbieterunabhängig.

## Nächste Schritte

- [Sending-Domains](/docs/guides/email/sending-domains): Registrierung, Verifizierungs-Lifecycle und die DNS-Records, die Sie veröffentlichen
- [Webhooks und Events](/docs/guides/webhooks): Endpoint-Einrichtung und Standard-Webhooks-Verifizierung
- [Test-Sandbox](/docs/guides/email/testing-sandbox): Smoke-Test der neuen Integration vor der Umstellung
- [Suppressions](/docs/guides/email/suppressions): importierte Liste prüfen und wie wir sie ab jetzt pflegen

## 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)
