# Migrare da Brevo

Questa pagina mappa il payload di invio transazionale, le blocklist e i webhook di Brevo su Bird. Segui la [guida principale alla migrazione](/docs/guides/email/migrate) nell'ordine indicato e usa queste corrispondenze per i passaggi 1, 3 e 4.

Brevo conserva le soppressioni in due posti non collegati tra loro, uno per la posta transazionale e uno per il marketing. Leggi [Esportare le soppressioni](#esportare-le-soppressioni) prima di pianificare il passaggio 3: esportare una lista e non l'altra è l'errore tipico di questa migrazione.

## Passa questa pagina al tuo agente

Incolla questo contenuto in Claude Code, Cursor o Codex. L'agente lavora su questa pagina nel tuo repository, usando qualsiasi superficie Bird già disponibile: il server MCP se ne è connesso uno, la CLI se è installata e autenticata.

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

## Mappare la chiamata di invio

`POST /v3/smtp/email` di Brevo e il nostro [`POST /v1/email/messages`](/docs/api/reference/create-email-message) hanno una struttura simile. Gran parte del lavoro consiste nello scomporre gli oggetti indirizzo di Brevo in semplici stringhe.

| Funzione               | Brevo                                          | Bird                                                                      |
| ---------------------- | ---------------------------------------------- | ------------------------------------------------------------------------- |
| Autenticazione         | Header `api-key`                               | `Authorization: Bearer`                                                   |
| Mittente               | `sender` (`{email, name}`)                     | `from`                                                                    |
| Destinatari            | `to` / `cc` / `bcc` (array di `{email, name}`) | `to` / `cc` / `bcc` (array di indirizzi)                                  |
| Oggetto                | `subject`                                      | `subject`                                                                 |
| Corpo                  | `htmlContent` / `textContent`                  | `html` / `text` (almeno uno)                                              |
| Reply-to               | `replyTo` (`{email, name}`)                    | `reply_to` (array)                                                        |
| Header personalizzati  | `headers` (chiavi in Title-Case)               | `headers` (oggetto stringa → stringa)                                     |
| Etichette filtrabili   | `tags` (array di stringhe)                     | Coppie `tags`: `{name, value}`                                            |
| Template salvato       | `templateId` + `params`                        | `template` + `template.parameters`                                        |
| Allegati               | `attachment` (`url` o base64 `content`)        | `attachments` (solo base64, vedi sotto)                                   |
| Pianificazione         | `scheduledAt`                                  | `scheduled_at`                                                            |
| Handle di batch        | `batchId`                                      | (nessun corrispettivo, vedi sotto)                                        |
| Copia per destinatario | `messageVersions`                              | un invio per versione, oppure un [batch](/docs/guides/email/sending-bulk) |
| Categoria              | (nessuna)                                      | `category`: `marketing` (predefinito) o `transactional`                   |

I limiti e i valori predefiniti dei campi (numero di destinatari, limiti di tag e metadati) si trovano in [Invio email](/docs/guides/email/sending-email).

Note sul porting:

- **Lì gli indirizzi sono oggetti, qui sono stringhe.** `{"email": "a@x.com", "name": "A"}` diventa `"A <a@x.com>"` o semplicemente `"a@x.com"`. La stessa scomposizione si applica a `sender` e `replyTo`.
- **`tags` sono semplici stringhe. I nostri tag sono coppie.** Un tag come `"welcome"` diventa `{"name": "category", "value": "welcome"}`. Scegli un `name` stabile in modo che le dashboard filtrino come facevano le statistiche dei tag su Brevo.
- **`params` è per i dati del template, non per il contesto di andata e ritorno.** Diventa `template.parameters`. Se lo usavi anche per trasportare i tuoi identificativi fino agli eventi, sposta quelli in [`metadata`](/docs/guides/email/sending-email), che restituiamo in ogni evento webhook insieme a `email_id`/`recipient_id`.
- **`messageVersions` non ha un equivalente in una singola chiamata.** Ogni versione è un set distinto di destinatari e payload, quindi diventa un invio a sé o una voce in un [batch](/docs/guides/email/sending-bulk).
- **`batchId` non ha un corrispettivo.** `batchId` di Brevo raggruppa i messaggi pianificati in modo da poterli annullare o ripianificare come insieme. Gli invii pianificati qui sono gestiti singolarmente tramite il loro message id; non esiste un handle di gruppo da passare o su cui operare l'annullamento.
- **L'allegato tramite URL non è supportato.** Brevo accetta una voce `attachment` come URL da cui scaricare il file. Scarica il file tu stesso e invialo codificato in base64; vedi [allegati](/docs/guides/email/attachments).

## Esportare le soppressioni

Brevo suddivide le soppressioni tra due sistemi che non condividono endpoint né schema di paginazione, e una migrazione che estrae solo il primo perde silenziosamente ogni disiscrizione marketing:

- **Blocchi e disiscrizioni transazionali**: `GET /v3/smtp/blockedContacts`, paginato (50 per pagina di default, 100 al massimo), con ogni voce che riporta il motivo del blocco.
- **Blocklist marketing**: non è affatto un endpoint di soppressione. Vive nel record del contatto come `emailBlacklisted`, quindi pagina `GET /v3/contacts` (fino a 1000 per pagina con `offset`) e conserva i contatti in cui quel flag è true.

Passa entrambe le liste attraverso il [ciclo di importazione](/docs/guides/email/migrate#3-import-suppressions). I motivi di blocco di Brevo corrispondono ai nostri motivi `hard_bounce`, `complaint` e `manual`; [Soppressioni](/docs/guides/email/suppressions) contiene la tassonomia completa.

## Tradurre gli eventi webhook

| Esito               | Brevo                       | Bird                                             |
| ------------------- | --------------------------- | ------------------------------------------------ |
| Accettato/elaborato | `request`                   | `email.accepted` → `email.processed`             |
| Consegnato          | `delivered`                 | `email.delivered`                                |
| Errore temporaneo   | `deferred` / `soft_bounce`  | `email.deferred`                                 |
| Bounce permanente   | `hard_bounce`               | `email.bounced` / `email.out_of_band_bounce`     |
| Segnalazione spam   | `spam`                      | `email.complained`                               |
| Bloccato/soppresso  | `blocked` / `invalid_email` | `email.rejected`                                 |
| Apertura            | `opened` / `unique_opened`  | `email.opened`                                   |
| Clic                | `click`                     | `email.clicked`                                  |
| Disiscrizione       | `unsubscribed`              | `email.unsubscribed` / `email.list_unsubscribed` |

Due differenze determinano quanto cambia il tuo handler.

**Verifica su cosa si basa oggi il tuo endpoint prima di portarlo.** La pagina di sicurezza dei webhook di Brevo documenta le credenziali che configuri sull'endpoint: un nome utente e una password aggiunti all'URL come `https://username:password@example.com/`, un bearer token, header di richiesta personalizzati e i suoi range di IP. Noi firmiamo ogni consegna secondo lo schema HMAC di [Standard Webhooks](https://www.standardwebhooks.com), quindi la verifica passa da qualcosa che il chiamante trasporta a qualcosa che il tuo handler calcola. Se il tuo endpoint attuale contiene credenziali nell'URL, rimuovile e ruota quella coppia invece di riutilizzarla: una credenziale che ha vissuto in un URL ha raggiunto log di accesso, export di configurazione e una console del fornitore. La procedura è in [Webhook ed eventi](/docs/guides/webhooks).

**Brevo distingue aperture e clic dalle loro varianti uniche. Noi no.** `opened` e `unique_opened` arrivano entrambi come `email.opened`, quindi un handler che contava solo la variante unica deve deduplicare direttamente su `recipient_id`. I nostri eventi di consegna sono a livello di destinatario, quindi un invio a tre destinatari produce tre esiti di consegna anziché uno.

## Cutover

Segui [domini e DNS](/docs/guides/email/migrate#2-re-point-domains-and-dns) e lo [smoke test in sandbox](/docs/guides/email/migrate#5-verify-in-the-sandbox-before-cutover) nella guida principale. Entrambi sono indipendenti dal provider.

## Prossimi passi

- [Domini di invio](/docs/guides/email/sending-domains): registrazione, ciclo di vita della verifica e i record DNS che stai pubblicando
- [Webhook ed eventi](/docs/guides/webhooks): configurazione dell'endpoint e verifica Standard Webhooks
- [Sandbox di test](/docs/guides/email/testing-sandbox): smoke test della nuova integrazione prima del cutover
- [Soppressioni](/docs/guides/email/suppressions): verifica la lista importata e come la manteniamo da qui in avanti

## Related resources

- [Getting started with email](/learn/email/getting-started-with-email) (video)
- [Email](/email-api) (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)
