Migrar desde Resend
Esta página asocia el payload POST /emails de Resend, el manejo de supresiones y los webhooks firmados con Svix con Bird. Sigue la guía principal de migración en orden y usa estas correspondencias para los pasos 1, 3 y 4. Los payloads de envío tienen campos similares, pero el seguimiento, los metadatos y la verificación de webhooks requieren cambios.
Pasa esto a tu agente
Pega esto en Claude Code, Cursor o Codex. El agente recorre esta página contra tu propio repositorio, usando la superficie Bird que ya tenga: el servidor MCP si hay uno conectado, o CLI si está instalado y con sesión iniciada.
Ejemplo de código
I am moving an email integration from Resend 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/resend.md for the payload, suppression and event mapping, and https://bird.com/docs/guides/email/migrate.md for the order the steps go in.
3. Find and list my Resend usage in this repository before you change anything: the POST /emails and batch call sites and any SDK wrappers around them, the webhook handler and the URL it is registered at, and every domain I send from.
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 my current provider 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. Rebuild my suppression list and import it into Bird before any production traffic goes through Bird, so my first sends do not reach addresses that already bounced or complained. Resend publishes no suppression export, so there is no endpoint that returns this list: derive it from whatever bounce and complaint events I have stored from my webhook, from the dashboard's Emails view, and from contacts marked unsubscribed in any Audience I use. That means the list can be incomplete without either of us noticing, so show me the list you built and tell me which of those sources each address came from before you import anything. 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. Verification is a header change rather than a rewrite here: Resend signs with Svix and Bird signs per Standard Webhooks, which is the same HMAC construction with the svix-* headers renamed to webhook-*, so keep my verifier and rename what it reads. The event shape does change: Resend's events are scoped to a message and Bird's are scoped to a recipient, so a send to three recipients yields three outcomes rather than one. See 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 Resend path is a separate step that comes later: ask me again and wait for me to reply with the words retire the Resend 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.Asociar la llamada de envío
| Función | Resend | Bird |
|---|---|---|
| Remitente | from | from |
| Destinatarios | to / cc / bcc | to / cc / bcc (arrays) |
| Asunto | subject | subject |
| Cuerpo | html / text | html / text (al menos uno) |
| Reply-to | reply_to | reply_to (array) |
| Encabezados personalizados | headers | headers (objeto string → string) |
| Etiquetas filtrables | tags: pares {name, value} | tags: pares {name, value} |
| Contexto de ida y vuelta | (ninguno; las etiquetas sirven como contexto) | metadata: JSON arbitrario |
| Programación | scheduled_at | scheduled_at |
| Seguimiento de aperturas/clics | configuración por dominio en el dashboard | track_opens / track_clicks (por defecto true) |
| Categoría | (ninguno) | category: marketing (por defecto) o transactional |
Los límites y valores por defecto de nuestros campos (cantidad de destinatarios, límites de etiquetas y metadatos) están en Enviar correo electrónico.
Notas de portabilidad:
- Las etiquetas mantienen su estructura, y metadata es una mejora. Las etiquetas de Resend son los mismos pares {name, value} que usamos, pero sus restricciones de valor obligaban a meter datos de correlación en los valores de las etiquetas. Aquí, mueve el contexto de correlación a metadata (JSON arbitrario, devuelto en cada evento de webhook y en las lecturas de API) y reserva las etiquetas para filtrar. Consulta etiquetas vs metadatos.
- El seguimiento pasa al payload. Resend activa o desactiva el seguimiento de aperturas/clics por dominio en el dashboard. Nosotros configuramos track_opens/track_clicks por mensaje (ambos por defecto true).
- scheduled_at se asocia directamente, nombre incluido. Consulta envío programado. Para react, renderiza tus plantillas de React Email a HTML en tu aplicación (la función render de @react-email/render funciona sin cambios) y envía el resultado como html.
- Los adjuntos se portan directamente. Los attachments de Resend (content en base64) se asocian con nuestro array de adjuntos. Usa content_id para imágenes en línea.
- El envío por lotes se porta directamente. El POST /emails/batch de Resend pasa a ser nuestro endpoint de lotes, con resultados por entrada en ambos casos.
Exportar supresiones
Resend no ofrece una exportación dedicada de la lista de supresiones. Extrae las direcciones cuyo último evento sea bounced o complained. Usa la vista Emails en el dashboard o tus eventos de webhook almacenados, y luego pasa la lista por el bucle de importación. Si usas Audiences para correo de marketing, transfiere también los contactos marcados como dados de baja.
Traducir eventos de webhook
| Resultado | Resend | Bird |
|---|---|---|
| Aceptado/procesado | email.sent | email.accepted → email.processed |
| Entregado | email.delivered | email.delivered |
| Fallo temporal | email.delivery_delayed | email.deferred |
| Rebote permanente | email.bounced | email.bounced / email.out_of_band_bounce |
| Queja de spam | email.complained | email.complained |
| Bloqueado/suprimido | email.failed | email.rejected |
| Apertura | email.opened | email.opened |
| Clic | email.clicked | email.clicked |
| Baja | (ninguno) | email.unsubscribed / email.list_unsubscribed |
La verificación de webhooks usa una construcción HMAC relacionada pero con encabezados diferentes. Resend usa svix-id, svix-timestamp y svix-signature. Bird sigue la especificación Standard Webhooks con encabezados webhook-*. Actualiza tu verificador para usar el secreto de firma de Bird y el procedimiento de Webhooks y eventos.
Una diferencia de comportamiento: los eventos de Resend tienen alcance de mensaje. Nuestros eventos de entrega tienen alcance de destinatario (recipient_id junto a email_id), así que un envío a tres destinatarios produce tres resultados de entrega, uno por destinatario.
Realizar el corte
Sigue los pasos de dominios y DNS y la prueba de humo en sandbox en la guía principal. Ambos son independientes del proveedor.
Próximos pasos
- Dominios de envío: registro, ciclo de vida de verificación y los registros DNS que estás redirigiendo
- Webhooks y eventos: configuración del endpoint y verificación con Standard Webhooks
- Sandbox de pruebas: prueba de humo de la nueva integración antes del corte
- Supresiones: confirma tu lista importada y cómo la mantenemos a partir de ahora
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Ver la guíaGetting started with emailExplorar la funcionalidadEmailSeguir la ruta de aprendizajeBuild your first integrationGuía de implementaciónSend your first email
Prueba el ejercicio y obtén un resumen de implementación