Migrar desde Resend
Sigue la guía principal de migración en orden y usa esta página para las correspondencias específicas de Resend en los pasos 1, 3 y 4. Los nombres de campo parecidos no hacen que las integraciones sean intercambiables: revisa los adjuntos, la validación de lotes, los valores predeterminados de categoría y seguimiento, el alcance de las restricciones y preferencias, la retención para reintentos y la verificación de webhooks. Mantén disponible la ruta anterior hasta que se cumplan las condiciones de observación y reversión acordadas.
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. Export the source team's provider suppressions using Resend's documented suppression API or dashboard CSV export. Separately inventory Contacts' global unsubscribe state, topic definitions and each contact's topic subscriptions, segment memberships, and my application's consent evidence. Read this guide's export and mapping section before proposing an import. Show me each source, capture time, page coverage, counts, exceptions, and target-owner mapping. An incomplete or failed export remains unresolved and gives no permission to send. Keep provider suppression provenance separately because Bird's public add creates a manual suppression applying to every category. Show me the proposed restriction and preference changes before importing; do not grant consent, infer a topic mapping, or unblock an address. Reconcile changes since the snapshot before production traffic.
6. Port each single-send and batch call site using this guide's field limits, attachment and batch differences, and retry rules. For webhooks, configure the Bird endpoint's signing secret, webhook-* headers, raw-body verification, and timestamp checks using the maintained Webhooks procedure. Do not assume a header rename completes verification. Preserve source event identity and reason. Map recipient outcomes separately from contact or suppression lifecycle events, and keep both provider handlers while late or in-flight events remain. Read 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 para el contenido incluido directamente) |
| Reply-to | reply_to | reply_to (array) |
| Encabezados personalizados | headers | headers (objeto de claves y valores de cadena; se rechazan los nombres reservados) |
| Etiquetas filtrables | tags: pares {name, value} | tags: misma estructura, límites más estrictos; consulta más abajo |
| Contexto de ida y vuelta | Contexto de la aplicación incluido en etiquetas | metadata: JSON arbitrario dentro de su límite de tamaño |
| Programación | scheduled_at | scheduled_at; revisa las restricciones de plantillas y programación |
| Seguimiento de aperturas/clics | Ajuste por dominio en el panel | track_opens / track_clicks por mensaje; valor predeterminado true |
| Categoría | Sin campo de envío equivalente | Categoría de la plantilla en envíos con plantilla; en los demás, marketing; indicar transactional expresamente no evita las restricciones |
| Identidad del reintento | Idempotency-Key | Idempotency-Key; distinta retención y sin deduplicación entre proveedores |
Consulta la referencia de envío de Resend junto con nuestros límites y valores predeterminados de los campos de envío. Adapta estas diferencias de forma explícita:
- Etiquetas y metadatos. Bird acepta hasta 20 etiquetas con nombres únicos, nombres de hasta 32 caracteres y valores de hasta 64 caracteres, con [A-Za-z0-9_-]. Resend permite 256 caracteres para un nombre o valor. Cuando corresponda, traslada los datos de correlación de la aplicación que sean demasiado grandes a metadata, dentro de su límite de 2 KB serializados. No trunques los identificadores sin avisar. Consulta etiquetas frente a metadatos.
- Seguimiento y categoría. Configura el seguimiento por mensaje. Un envío con plantilla usa de forma predeterminada la categoría de esa plantilla; los demás envíos usan marketing. Las bajas y supresiones aplicables bloquean el correo de marketing. transactional puede superar una baja de correo no transaccional o una queja nativa, pero las supresiones manuales, las debidas a rebotes permanentes y las preferencias que abarcan todo el tráfico siguen bloqueándolo. Revisa la política de supresiones antes de cambiar la categoría.
- Programación y React. Adapta scheduled_at según las restricciones del envío programado. Para el parámetro react de Resend, renderiza la plantilla de React Email a HTML en tu aplicación con @react-email/render y envía el resultado como html.
- Adjuntos. Resend admite un path alojado o el contenido del adjunto. Bird requiere filename y content en base64, sin campo para una ruta alojada. Recupera y codifica los archivos alojados dentro de tu aplicación existente, con sus controles de acceso a URL. Valida el tipo MIME y el content_id de los adjuntos insertados según nuestro contrato de adjuntos. Bird permite hasta 20 adjuntos dentro de un límite estimado de 20 MB para el mensaje generado; Resend documenta un límite de 40 MB para los adjuntos codificados. Comprueba el mensaje generado completo y los límites de destinatarios antes de enviarlo.
- Solicitudes por lotes y resultados. La referencia de lotes de Resend acepta un array de nivel superior de hasta 100 objetos de envío y devuelve un array data de IDs; no admite adjuntos. Bird acepta {"messages":[...]} con 1–100 objetos de envío completos. Bird valida todos los elementos antes de poner alguno en cola: un elemento no válido o un remitente no verificado hace que se rechace el lote con 422. Los destinatarios suprimidos pueden aceptarse y registrar después un rechazo del destinatario. Una respuesta 202 correcta devuelve IDs secundarios ordenados para seguirlos individualmente; la aceptación no demuestra la entrega. Bird admite adjuntos y programación por elemento, sujetos al límite por mensaje y a un máximo de 20 MB para el cuerpo del lote serializado. Usa validación de lotes y resultados; no deduzcas cómo gestiona Resend los fallos o los resultados parciales a partir de su ejemplo de respuesta correcta.
Reintentos entre llamadas a SDK. Guarda de forma persistente un ID de operación de la aplicación y una clave de idempotencia explícita para cada envío lógico. Nuestro SDK genera una clave dentro de una llamada y la reutiliza en los reintentos internos de esa llamada. Volver a llamar al envío sin tu clave explícita original crea otra invocación y otra clave.
Bird conserva las respuestas completadas durante tres horas; Resend documenta un plazo de 24 horas. Tras su vencimiento, un reintento en Bird puede ejecutarse de nuevo. Las claves no deduplican entre proveedores. Bird no conserva las respuestas 5xx, y una operación puede surtir efecto antes de que se conserve su respuesta. Un tiempo de espera agotado, una respuesta perdida o un bloqueo de operación en curso caducado dejan el resultado del envío sin determinar.
Concilia los registros de la aplicación y los IDs de mensaje de los proveedores antes de cambiar de proveedor o reintentar operaciones con resultado incierto. Gestiona los conflictos por operaciones en curso y solicitudes modificadas mediante el procedimiento de idempotencia, las opciones de clave explícita entre llamadas y la guía de reintentos de SDK.
Exporta las supresiones
Resend documenta una lista de supresiones mediante API y la exportación CSV desde el panel. Confirma el acceso en el equipo de origen y recorre todas las páginas de resultados. Conserva el ID de origen, la procedencia y la referencia de origen de cada dirección, además del momento de captura, las páginas cubiertas, los recuentos y las excepciones. Los ejemplos de la documentación no demuestran la disponibilidad para tu cuenta.
Usa los eventos almacenados para conciliar los cambios desde la instantánea. Una exportación no disponible o incompleta sigue sin resolverse. Exporta los siguientes registros por separado: una lista de supresiones vacía, la pertenencia a una audiencia o una restricción eliminada no demuestran consentimiento.
| Registro de origen | Tratamiento en destino y restricción |
|---|---|
| Supresión del proveedor: correo, procedencia y referencia de origen | El POST /v1/email/suppressions público de Bird crea manual, que bloquea todas las categorías. Conserva el motivo original y la procedencia en el registro de migración de tu aplicación; este API no importa el motivo de origen. Revisa la política más estricta antes de importar. |
| unsubscribed del contacto | Registra la baja global de correo revisada mediante el responsable de las preferencias, con pruebas del estado real y de la cobertura. Un indicador de origen con valor false no basta para revertir una baja existente en Bird. |
| Definiciones de temas, valores predeterminados y suscripciones temáticas de cada contacto | Conserva las definiciones y las elecciones registradas. El esquema público de escritura de preferencias de Bird no tiene campo de tema; las preferencias de correo abarcan todo el canal. Mantén las restricciones específicas de cada finalidad en el responsable existente de permisos y selección de destinatarios de tu aplicación hasta acordar una correspondencia explícita. No amplíes el conjunto de destinatarios aptos. |
| Pertenencia a segmentos | Adapta la agrupación revisada a audiencias estáticas de Bird y a IDs reales de contacto, conciliando incorporaciones y eliminaciones. La pertenencia no otorga consentimiento; los cambios en las propiedades no recalculan una audiencia estática. |
| Pruebas de consentimiento de la aplicación | Conserva la finalidad, la procedencia y las marcas de tiempo con su responsable existente. No inventes fechas de consentimiento a partir de la hora de exportación ni de los valores predeterminados del proveedor. Excluye del piloto las cohortes sin resolver. |
Para las exportaciones de origen, usa los contactos, las definiciones de temas, los temas de los contactos y los segmentos de los contactos de Resend. Para las correspondencias de destino, revisa las preferencias, la gestión de bajas, los contactos, las audiencias y la sincronización de pertenencia.
Sigue la importación pública de supresiones para una sola dirección, inspecciona cada respuesta y concilia los IDs y recuentos devueltos con el registro de origen. Un registro manual nuevo devuelve 201; uno manual existente devuelve 200 sin cambios. Importar manualmente una queja bloquea también el correo transaccional. Consulta las coincidencias exactas de direcciones completas en todas las páginas: el filtro de correo de Bird busca por prefijos. Que termine un bucle de shell no demuestra por sí solo que la importación se haya completado correctamente. Vuelve a conciliar los cambios de la instantánea antes de enviar tráfico y antes de revertir. La ruta masiva exclusiva del panel no es un endpoint público de migración.
Las escrituras de preferencias son upserts con reglas de autoridad y orden. Inspecciona applied y el registro que queda vigente aunque la respuesta sea 200. Revertir una baja almacenada exige pruebas reales de consentimiento posterior; una autorización declarada en nombre de alguien no puede anular su propia baja. Borrar supresiones no elimina las preferencias. Consulta la gestión de supresiones y el contrato de escritura de preferencias.
Adapta los eventos de webhook
Usa esta tabla para interpretar el evento de origen y localizar su responsable en Bird. No es una regla universal para renombrar eventos. Consulta la referencia de eventos de Resend y nuestros eventos de correo.
| Evento de origen de Resend | Interpretación y responsable en Bird |
|---|---|
| email.sent | Aceptación o avance del intento, sin prueba de entrega. email.accepted y email.processed de Bird son observaciones distintas del ciclo de vida del destinatario. |
| email.delivered | Aceptación por el servidor receptor; Bird email.delivered. |
| email.delivery_delayed | Fallo temporal de entrega; Bird email.deferred. |
| email.bounced | Rebote permanente; Bird email.bounced o email.out_of_band_bounce, según el momento en que ocurra. |
| email.complained | Queja por spam; Bird email.complained. |
| email.failed | Conserva el error y la identidad de origen. Determina si Bird rechaza la solicitud de forma síncrona o rechaza a un destinatario por un motivo concreto. No clasifiques todos los fallos como email.rejected ni como direcciones con rebote. |
| email.suppressed | Resultado de un envío bloqueado. El resultado de destinatario comparable en Bird es email.rejected con recipient_suppressed; ese motivo abarca las preferencias aplicables y los registros de supresión. |
| email.opened | Carga del píxel de seguimiento; Bird email.opened. |
| email.clicked | Solicitud de un enlace con seguimiento; Bird email.clicked. |
| suppression.added | Ciclo de vida de una restricción, separado de la entrega. Concilia la procedencia y la política; Bird registra las incorporaciones como email_suppression.created. |
| suppression.removed | Ha cambiado una restricción; esto no demuestra consentimiento. Revisa las restricciones y preferencias restantes antes de eliminar nada en Bird. No inventes un evento Bird equivalente ni desbloquees automáticamente la dirección. |
| contact.updated y estado de preferencias inspeccionado | Las actualizaciones pueden incluir unsubscribed; inspecciona el valor antes de registrar una baja. Concilia el estado y la procedencia por separado de los eventos de destinatario email.unsubscribed y email.list_unsubscribed de Bird. Inspecciona el estado de los temas mediante su propia fuente. |
Resend usa svix-id, svix-timestamp y svix-signature. Bird usa webhook-id, webhook-timestamp y webhook-signature. Sigue Webhooks y eventos con el secreto de firma del endpoint de Bird, el cuerpo sin procesar de la solicitud y las comprobaciones de tolerancia de marcas de tiempo. Cambiar solo los nombres de las cabeceras no demuestra una verificación correcta.
Deduplica por proveedor e identidad del evento. Conserva las marcas de tiempo de origen, los motivos originales, los IDs de mensaje y los IDs de destinatario de Bird. Los eventos de envío de Resend corresponden al mensaje; los eventos de entrega de Bird incluyen un recipient_id junto a email_id. Registra los resultados observados por destinatario sin inventarlos multiplicando un evento de mensaje del origen. Comprueba los casos de eventos retrasados, duplicados y con firma no válida en tu manejador, y conserva los manejadores de ambos proveedores mientras queden operaciones tardías pendientes.
Cambia el tráfico
Completa dominios y DNS y la prueba básica en sandbox de la guía principal. Antes de cambiar el enrutamiento de producción, revisa el registro de migración de abajo. Indica los responsables del enrutamiento, la aprobación y la reversión, la cohorte apta para el envío, la referencia inicial, el intervalo de observación y los umbrales de parada. Confirma la conciliación de restricciones y preferencias, los cambios de la instantánea, la autenticación del remitente, la verificación de webhooks y los casos representativos de renderizado, adjuntos y mensajes programados.
Conserva los registros de envío anteriores y revisa por separado los MX de recepción. Una prueba de sandbox superada aporta pruebas para decidir el cambio de tráfico; espera la aprobación explícita del prompt del agente antes de enrutar tráfico de producción.
Cambia la cohorte apta para el envío y aprobada mediante un único responsable de enrutamiento, sin envíos duplicados. Si se alcanza un umbral de parada, detén el nuevo enrutamiento y concilia las operaciones aceptadas, en curso, programadas y de resultado incierto, además de las nuevas restricciones. Confirma la cancelación de los envíos programados antes de trasladar esas operaciones. Devuelve las operaciones aptas aún no enviadas a la ruta anterior sin repetir a ciegas envíos ambiguos entre proveedores. Mantén ambos consumidores de eventos y la autenticación hasta que terminen las operaciones tardías pendientes. Retirar Resend requiere una autorización explícita independiente.
Registro de migración para copiar. Complétalo con referencias a los registros existentes de tu aplicación. Los campos vacíos no otorgan aprobación; los registros existentes de la aplicación siguen siendo la autoridad. No incluyas credenciales en el registro.
Ejemplo de código
Migration owner / routing owner / rollback owner / approver:
Source team / target workspace and region:
Application operation-record location:
Send and batch call sites / SDK wrappers / templates / React rendering:
Category and tracking decisions / attachment and batch adjustments:
Sending domains / side-by-side DNS / separate receiving MX decision:
For each source below: capture time, page/cursor coverage, counts, errors,
source-to-target mapping, imported or preserved counts, and delta watermark:
- Provider suppressions, original reasons, and source references:
- Contacts' global unsubscribe state:
- Topic definitions/defaults and each contact's subscriptions:
- Segment memberships and target contact IDs:
- Application purpose, consent evidence, and timestamps:
Unresolved mappings / excluded cohort / review owner:
Snapshot delta reconciliation before traffic and rollback:
Stable application operation IDs and explicit keys / provider message IDs:
Uncertain outcomes / reconciliation evidence / retry-window decisions:
Sandbox accepted, suppressed, bounce, complaint, and invalid-request evidence:
Representative rendering / attachments / scheduled-message evidence:
Raw-body signature / timestamp / duplicate / delayed / invalid-event evidence:
Eligible pilot cohort / baseline / observation interval / stop thresholds:
Explicit cut over to Bird approval (person, time, and record):
Observed recipient outcomes and event lag:
Rollback stop and routing owner / accepted, in-flight, or uncertain work:
Scheduled cancellation confirmations / eligible unsent operations:
New restriction and preference reconciliation / remaining exceptions:
Late-event consumers / retained DNS and authentication / drain evidence:
Separate retire the Resend path approval (person, time, and record):Siguientes pasos
- Dominios de envío: registro, ciclo de verificación y registros DNS que vas a redirigir
- Webhooks y eventos: configuración del endpoint y verificación con Standard Webhooks
- Sandbox de pruebas: prueba básica de la nueva integración antes de cambiar el tráfico
- Supresiones: confirma tu lista importada y cómo la mantenemos a partir de ese momento
Consulta la comparativa entre Bird y Resend para decidir qué producto elegir, o sigue con los recursos de email para acceder a las guías de implementación y operación.
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