# Migrar SMS desde otro proveedor

Usa esta guía para mover SMS en producción desde otro proveedor a Bird. Dos cosas condicionan un primer envío aquí que tu proveedor actual gestiona de forma distinta, así que van antes del código: los países a los que envías y el remitente desde el que envías. Después, adapta la llamada de envío, traslada tu lista de exclusiones voluntarias, redirige los informes de entrega a webhooks y prueba contra destinos simulados antes de mover tráfico real.

Lista de verificación de la migración:

1. [Habilita tus países de destino](#1-habilita-tus-países-de-destino)
2. [Configura un remitente](#2-configura-un-remitente)
3. [Adapta la llamada de envío](#3-adapta-la-llamada-de-envío) a `POST /v1/sms/messages`
4. [Traslada tu lista de exclusiones voluntarias](#4-traslada-tu-lista-de-exclusiones-voluntarias)
5. [Redirige los informes de entrega a webhooks](#5-redirige-los-informes-de-entrega-a-webhooks)
6. [Prueba contra destinos simulados](#6-prueba-contra-destinos-simulados) antes del corte

Los pasos 3, 4 y 5 dependen del proveedor que estás dejando. Tu [guía de proveedor](#migrar-desde-un-proveedor-específico) contiene el mapeo campo por campo del payload, la traducción de estados y eventos, y dónde obtener tu lista de exclusiones voluntarias.

Comienza con los pasos 1 y 2. El registro del remitente es lo que más tarda en una migración de SMS: la revisión del operador y el registro puede durar más que el cambio de código. Evalúa ambos antes de fijar una fecha de corte.

## 1. Habilita tus países de destino

Tu espacio de trabajo tiene una lista de destinos permitidos que deniega por defecto y empieza solo con el país de origen de tu organización habilitado. Un envío a cualquier otro lugar devuelve `422 SMSDestinationNotEnabled` antes de que Bird resuelva un remitente, así que una integración que portaste fielmente sigue fallando en su primer mensaje internacional hasta que abras el país.

Habilita cada país al que envías bajo [**SMS** > **Destinations**](https://bird.com/dashboard/w/sms/destinations). Toma la lista de los registros de mensajes de tu proveedor actual en lugar de hacerlo de memoria: un país que olvides es un vacío silencioso el día del corte, y un país que habilites pero nunca uses es exposición innecesaria. Denegar por defecto también es lo que limita el daño del SMS pumping, donde tráfico fraudulento a rangos premium se te factura a ti.

## 2. Configura un remitente

En un envío de texto libre, `from` es el remitente que ve tu destinatario y adopta una de tres formas: un sender ID alfanumérico, un número de teléfono en E.164 que tu espacio de trabajo posee, o un código corto. Las formas válidas dependen del país de destino, y un remitente que no sea válido allí se rechaza con un `422` que indica el motivo. [Enviar SMS](/docs/guides/sms/sending-sms#sender) tiene las reglas por forma.

Cómo obtener cada uno:

- Los **sender ID alfanuméricos** los creas tú bajo [**SMS** > **Senders**](https://bird.com/dashboard/w/sms/senders). Si el país de destino requiere que el sender ID esté registrado, envía el registro allí y espera la aprobación antes de dirigir tráfico hacia él.
- El **tráfico comercial en EE. UU. a través de códigos largos locales** necesita la marca y campaña 10DLC correspondientes, configuradas en [**SMS** > **10DLC**](https://bird.com/dashboard/w/sms/10dlc), mientras que los números gratuitos y los códigos cortos dedicados tienen sus propios programas de verificación o solicitud. EE. UU. no acepta sender ID alfanuméricos en absoluto, por lo que un sender ID europeo que funciona en todas partes no tiene equivalente en EE. UU.
- Los **números** se obtienen a través del flujo de Numbers, con disponibilidad y aprovisionamiento gestionado que dependen del tipo y el destino. Consulta [números de SMS](/products/sms/numbers) para la ruta correcta; añadir un remitente alfanumérico no adquiere un número.
- **Conservar tus números actuales** no es autoservicio: Bird no tiene un flujo de portabilidad que puedas ejecutar desde el panel. Si tus suscriptores responden a números que posees hoy, inicia la portabilidad con soporte antes de programar una fecha de corte, y planifica que la portabilidad y el cambio de código sean eventos separados.

Un [envío con plantilla de sistema](/docs/guides/sms/templates) usa un formulario de solicitud diferente. Sigue necesitando el destino y el permiso de destinatario aplicables. Proporciona el cuerpo, la categoría y el remitente, así que `from` no se acepta junto con él y Bird elige un remitente válido para el destino.

## 3. Adapta la llamada de envío

El endpoint de envío individual es [`POST /v1/sms/messages`](/docs/api/reference/create-sms-message). Construye un payload JSON con `to`, `from`, `text` y `category`, y una llamada exitosa devuelve `202 Accepted` con un ID de mensaje con prefijo `sms_`. La entrega ocurre después de la respuesta y te llega a través de eventos de webhook y los endpoints de lectura. El payload completo está en [Enviar SMS](/docs/guides/sms/sending-sms); el mapeo campo por campo desde tu payload actual está en tu [guía de proveedor](#migrar-desde-un-proveedor-específico).

Antes de portar código, ten en cuenta estas diferencias:

- **Un destinatario por solicitud.** Bird no tiene un array de destinatarios. Si tu proveedor actual distribuye una llamada a muchos números, eso se convierte en una llamada por destinatario, o un [lote](/docs/guides/sms/sending-sms#batch-sending) de mensajes independientes en una sola solicitud.
- **`category` es obligatorio en texto libre**, y es `transactional`, `marketing`, `authentication` o `service`. La mayoría de proveedores infieren la intención de la campaña o el remitente; aquí lo declaras por mensaje, y cuando el país de destino requiere que el remitente esté registrado, ese registro se aprueba para una categoría y un envío fuera de ella se rechaza con `422 SenderCategoryNotPermitted`. El estado `active` del remitente no puede indicarte esto de antemano, porque se reporta sin referencia a ninguna categoría; consulta los requisitos por país en su lugar. Configúralo correctamente en la portabilidad en vez de asignar todo a un solo valor.
- **El cuerpo está limitado en segmentos, y Bird no trunca.** Un cuerpo más largo se rechaza con un `422`. Los caracteres fuera de GSM-7 reducen a menos de la mitad lo que cabe en un segmento, así que si tu proveedor actual transliteraba silenciosamente comillas tipográficas y guiones, activa [`options.smart_encoding`](/docs/guides/sms/sending-sms#segments-and-encoding) para mantener los conteos de segmentos a los que estás acostumbrado. Está desactivado por defecto porque altera el cuerpo que compusiste.
- **Usa `tags` para dimensiones de filtrado y `metadata` para contexto.** Los tags son pares `{name, value}` por los que puedes filtrar y segmentar analíticas; los metadatos son JSON arbitrarios que Bird almacena, devuelve en lecturas y repite en cada evento de webhook. Un campo de referencia de cliente único en tu proveedor anterior normalmente se mapea a `metadata`.
- **La programación de envíos individuales y MMS saliente necesitan un plan aparte.** `scheduled_at`, `media_urls`, `validity_period` y `personalization` por destinatario son [campos reservados](/docs/guides/sms/sending-sms#reserved-fields), rechazados con `422 SMSUnsupportedFeature`. Esas partes de tu integración no se mueven con el resto: mantén los envíos programados en tu propia cola y llama al endpoint de envío en el momento de envío previsto. Para campañas de audiencia, evalúa [Broadcasts](/products/sms/marketing/campaigns) por separado; un broadcast no es un renombramiento de campo del endpoint.
- **Usa `Idempotency-Key` para reintentos acotados.** Envía una clave única por mensaje lógico y reutilízala para reintentos de la solicitud idéntica dentro de la ventana de repetición de tres horas. Las repeticiones reducen solicitudes duplicadas, pero no son una garantía de entrega exactamente una vez. Consulta [Idempotency](/docs/guides/idempotency).

## 4. Traslada tu lista de exclusiones voluntarias

Importa tus exclusiones voluntarias **antes** del primer envío en producción. Enviar un mensaje a alguien que le dijo a tu proveedor anterior que parara es el fallo de cumplimiento que arruina una migración, y ni al operador ni al regulador le importa qué proveedor perdió el registro.

Una supresión en Bird cubre un **par remitente-suscriptor**, que puede ser más estrecho que el bloqueo a nivel de servicio, perfil o cuenta de tu proveedor anterior. Preserva la revocación real de la persona en cada remitente y programa relevante. Añade cada par con [`POST /v1/sms/suppressions`](/docs/api/reference/create-sms-suppression):

```bash
while IFS=, read -r destination originator; do
  curl -s -X POST https://us1.platform.bird.com/v1/sms/suppressions \
    -H "Authorization: Bearer $BIRD_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"destination\": \"$destination\", \"originator\": \"$originator\"}"
done < opt-outs.csv
```

La misma importación se ejecuta desde CLI como `bird sms suppressions add --destination +15550001234 --originator +15557654321`.

Dos cosas que debes saber sobre la importación:

- **Ambos extremos son obligatorios para supresiones específicas por remitente.** Una exclusión voluntaria a nivel del espacio de trabajo pertenece al [preference owner](/docs/guides/sms/opt-outs-and-keywords#opting-out-of-every-sender) separado. La llamada es idempotente: `201` registra una nueva supresión, `200` devuelve la manual ya existente, así que volver a ejecutar una importación parcial es seguro.
- **Los pares importados reciben `reason: manual`, que bloquea todas las categorías incluida la transaccional.** Eso es más estricto que una supresión que Bird registra por sí mismo a partir de una palabra clave de parada. Si un suscriptor solo rechazó marketing, decide deliberadamente si importar ese par.

Revisa el comportamiento existente de palabras clave y preferencias antes de retirar código. Bird responde las palabras clave soportadas y registra supresiones donde aplica su catálogo de países. Conserva la gestión de solicitudes no soportadas, preferencias más amplias y otros canales de contacto. Las palabras clave y respuestas personalizadas de campaña usan [Keyword rules](https://bird.com/dashboard/w/sms/keyword-rules). Consulta [Exclusiones voluntarias y palabras clave](/docs/guides/sms/opt-outs-and-keywords) para cobertura y alcance.

## 5. Redirige los informes de entrega a webhooks

Registra un endpoint con [`POST /v1/webhooks`](/docs/api/reference/create-webhook) y suscríbelo a una lista explícita de tipos de eventos. Este es el cambio estructural que la mayoría de proveedores requieren: en lugar de una URL de callback por mensaje o por número, tu espacio de trabajo tiene endpoints, y cada endpoint se suscribe a los eventos que quiere.

Los nombres de eventos de Bird siguen `resource.action`. El camino exitoso es `sms.accepted`, luego `sms.sent`, luego `sms.delivered`, con `sms.undelivered`, `sms.failed`, `sms.expired` y `sms.rejected` cubriendo el resto, y `sms.received` transportando respuestas a tus números. La traducción desde el vocabulario de estados de tu proveedor actual está en tu [guía de proveedor](#migrar-desde-un-proveedor-específico), y los payloads por evento están en [eventos de SMS](/docs/guides/sms/events).

La correlación se porta limpiamente. Cada evento lleva `sms_id`, `workspace_id`, `to` y `from`, y repite `tags` y `metadata` del envío, así que tu handler lee tus propios identificadores directamente del evento en lugar de buscar el mensaje.

Dos mecánicas que portar con el handler:

- **Las entregas se firman según [Standard Webhooks](https://www.standardwebhooks.com)**, usando los headers `webhook-id`, `webhook-timestamp` y `webhook-signature` con un HMAC-SHA256 sobre `{id}.{timestamp}.{raw body}`. Los proveedores que firman con su propio esquema necesitan que se reemplace la verificación; la receta está en [Webhooks & events](/docs/guides/webhooks#verify-signatures).
- **La entrega es al menos una vez y sin orden.** Deduplica por `webhook-id` y ordena por el `timestamp` del payload, nunca por orden de llegada.

Los mensajes entrantes siguen el mismo modelo. Suscríbete a `sms.received` una vez para el espacio de trabajo en lugar de configurar una URL de entrada por número, y recuerda que Bird sigue emitiendo `sms.received` para una respuesta que coincidió con una palabra clave de parada, después de registrar la supresión.

## 6. Prueba contra destinos simulados

Bird sintetiza resultados de entrega para un conjunto de destinos de prueba, así que puedes ejercitar tu ruta de envío portada y tu handler de webhook contra respuestas reales de API y entregas firmadas reales sin un dispositivo. Son los mismos números que varios proveedores usan para credenciales de prueba, y un mensaje a uno de ellos nunca llega a un operador.

| Destino        | Lo que ve tu integración                                  |
| -------------- | --------------------------------------------------------- |
| `+15005550001` | Rechazado en el envío con `invalid_destination`           |
| `+15005550002` | `sms.sent`, luego `sms.undelivered` con `unreachable`     |
| `+15005550003` | `sms.sent`, luego `sms.failed` con `provider_unavailable` |
| `+15005550004` | `sms.sent`, luego `sms.failed` con `blocked_by_carrier`   |
| `+15005550006` | `sms.sent`, luego `sms.delivered`                         |
| `+15005550009` | `sms.sent`, luego `sms.failed` con `recipient_opted_out`  |

Tres condiciones aplican, y las dos primeras suelen fallar en un espacio de trabajo nuevo:

- Son números de EE. UU., así que **Estados Unidos debe estar habilitado** en Destinations, y `from` debe ser un remitente válido para EE. UU. Un sender ID alfanumérico se rechaza allí.
- **Un envío simulado se factura** a la tarifa normal del destino. Nada llega a un dispositivo, pero el cargo en la billetera es real, así que dimensiona tu prueba de humo en consecuencia.
- El resultado depende solo del destino. No hay una credencial de prueba separada ni un modo de prueba que desactivar.

Una prueba de humo viable envía a `+15005550006` y verifica que tu handler recorre `sms.accepted` a `sms.sent` a `sms.delivered`; envía a `+15005550002` y `+15005550009` y verifica que tu manejo de fallos y exclusiones voluntarias se activa con el código `error` correcto; y envía un mensaje real a un dispositivo que controles para confirmar que el remitente y el cuerpo se muestran como esperas.

Después, haz el corte por porcentaje de tráfico en vez de todo a la vez. Mueve un porcentaje pequeño de envíos en producción a Bird, observa el [registro de SMS](/docs/guides/sms/sms-log) y las [métricas](/docs/guides/sms/tracking-and-metrics) en busca de tasas de entrega y códigos de error comparados con lo que tu proveedor anterior reportaba para las mismas rutas, y sube el porcentaje a medida que los números se sostengan. Mantén la integración anterior desplegable hasta que el primer período de facturación completo se vea bien.

## Migrar desde un proveedor específico

- [Twilio](/docs/guides/sms/migrate/twilio): `PascalCase` form-encoded a JSON, Messaging Services a remitentes, `StatusCallback` a webhooks suscritos
- [Plivo](/docs/guides/sms/migrate/plivo): `src` y `dst` a `from` y `to`, Powerpacks a remitentes, pares DND a supresiones
- [Telnyx](/docs/guides/sms/migrate/telnyx): el envío más parecido al de Bird, perfiles de mensajería separados en remitentes y suscripciones, exclusiones voluntarias a nivel de perfil a pares
- [Bandwidth](/docs/guides/sms/migrate/bandwidth): dos hosts a uno, callbacks `applicationId` a webhooks del espacio de trabajo, y una lista de exclusiones voluntarias que tu propia aplicación ya mantiene
- [Sinch](/docs/guides/sms/migrate/sinch): lotes a envíos individuales, `body` a `text`, membresía de grupo reconstruida como supresiones
- [Infobip](/docs/guides/sms/migrate/infobip): un payload de tres niveles aplanado, una URL base por cuenta a un host regional, una Blocklist expandida a pares
- [Bird Connectivity Platform](/docs/guides/sms/migrate/connectivity-platform): el `rest.messagebird.com` API, `originator` y `recipients` a `from` y `to`, callbacks GET `reportUrl` a webhooks firmados

## Próximos pasos

- [Comparar proveedores de SMS](/products/sms/compare): evalúa el flujo de producto y las consideraciones de migración

- [Enviar SMS](/docs/guides/sms/sending-sms): el payload de envío completo, remitentes, segmentos y el modelo asíncrono 202
- [Exclusiones voluntarias y palabras clave](/docs/guides/sms/opt-outs-and-keywords): lo que Bird responde por ti y cómo gestionar supresiones
- [Eventos de SMS](/docs/guides/sms/events): el vocabulario de eventos y los payloads por evento
- [Webhooks & events](/docs/guides/webhooks): configuración de endpoints, verificación de firma, reintentos y repetición

## Related resources

- [Choose a sender for your markets](/explained/sms/which-sms-sender-type-should-i-use) (answer)
- [Check your message segments](/tools/sms-segment-calculator) (tool)
