# Migrar Verify desde Prelude

Esta página mapea las API de verificación v2 de Prelude a Bird Verify. Sigue la [guía principal de migración](/docs/guides/verify/migrate) en orden y usa estos mapeos para los pasos 1 y 3.

Las estructuras son similares. `POST https://api.prelude.dev/v2/verification` y `POST /v2/verification/check` de Prelude son un par create-and-check con autenticación bearer indexado por el destinatario en lugar de por un ID de verificación, e igual funcionan [`POST /v1/verify/verifications`](/docs/api/reference/create-verification) y [`POST /v1/verify/verifications/check`](/docs/api/reference/create-verification-check). Llamar a create de nuevo para un destinatario activo reintenta en lugar de iniciar una verificación nueva en ambas plataformas. Lo que no se porta es la capa de riesgo: los signals, veredictos de enrutamiento y verificación silenciosa de Prelude no tienen equivalente en la API de Bird Verify.

## Pasa esto a tu agente

Pega esto en Claude Code, Cursor o Codex. El agente trabaja con esta página sobre tu propio repositorio, usando la superficie de Bird que ya tenga: el servidor MCP si hay uno conectado, o CLI si está instalado y con sesión iniciada.

```text
I am moving a phone verification integration from Prelude to Bird Verify. 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/verify/migrate/prelude.md for the create, check and status mapping, and https://bird.com/docs/guides/verify/migrate.md for the order the steps go in.
3. Find and list my Prelude usage in this repository before you change anything: the /v2/verification and /v2/verification/check call sites, anywhere I read signals or a routing verdict, and anywhere I use dispatch_id for retry safety.
4. Tell me early which of these I depend on. Bird Verify has no voice channel and no silent or network-based authentication. It generates the code itself and never returns it, so I cannot supply my own. It accepts `options.language` but no per-request template or message body. Bird can use an existing SMS Sender ID or a connected WhatsApp number with an approved authentication template, configured per channel or country rather than per request; tell me whether my current sender can be kept. Prelude's risk layer does not port either: its signals, its routing verdicts and its silent verification have no counterpart in Bird Verify, so tell me every decision my code makes on those.
5. Configure my channels and destinations following https://bird.com/docs/guides/verify/countries.md and https://bird.com/docs/guides/verify/senders.md. While you are there, disable every country I do not actually verify into. An enabled destination I never send to is not reach, it is exposure to SMS pumping, so ask me which countries I serve rather than leaving the defaults.
6. Port the create and check calls using the mapping tables on the provider page, and move my status handling to Bird's events: https://bird.com/docs/guides/verify/sending-verifications.md and https://bird.com/docs/guides/verify/events.md.
7. Cut over at the create call, not all at once, because a code issued by Prelude cannot be checked by Bird and a code issued by Bird cannot be checked by Prelude. From the moment I say go, send every NEW verification to Bird, and keep routing each check to whichever provider issued that verification. Keep both paths live for one full code lifetime plus margin, then retire the old one. Tell me how you will decide which provider issued a given verification before you write any of it.
8. Test before any real traffic. Bird Verify has no simulated recipients, so do not look for a sandbox: the thing worth testing is the code arriving. Run the integration against a phone number and a mailbox I control, on each channel I enabled, and show me what arrived on each one.
9. Stop and ask me wherever a step needs a decision. Do not start routing new verifications to Bird until I have seen those test results and replied with the words cut over to Bird. Retiring the Prelude path is a separate step: ask me again and wait for me to reply with the words retire the Prelude path, and do not retire it while any code it issued could still be checked. 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.
```

## Mapear la llamada create

| Qué hace                | Prelude                                                                          | Bird                                                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Destinatario            | `target.type` + `target.value`                                                   | `to.phone_number` o `to.email`                                                                                              |
| Longitud del código     | `options.code_size`                                                              | `options.code_length`                                                                                                       |
| Preferencia de canal    | `options.preferred_channel`, `options.channels`                                  | `options.channels`, o si no, el orden configurado del país                                                                  |
| Correlación             | `metadata.correlation_id`                                                        | `metadata`                                                                                                                  |
| Callbacks de entrega    | `options.callback_url`                                                           | un webhook del espacio de trabajo suscrito a los tipos de evento de Verify que indiques                                     |
| Código personalizado    | `options.custom_code`                                                            | sin equivalente                                                                                                             |
| Localización            | `options.locale`                                                                 | `options.language`                                                                                                          |
| Identidad del remitente | `options.sender_id`                                                              | selecciona un remitente gestionado por Bird o propio del espacio de trabajo por canal o país, no por solicitud              |
| Plantilla de mensaje    | `options.template_id`, `options.variables`                                       | sin equivalente por solicitud; selecciona una plantilla de autenticación de WhatsApp aprobada en la configuración de Verify |
| Autocompletado Android  | `options.app_realm`                                                              | sin equivalente                                                                                                             |
| Señales de riesgo       | `signals` (IP, dispositivo, huella)                                              | no se aceptan                                                                                                               |
| Reintentos seguros      | sin clave ni encabezado de idempotencia en su referencia de create o check       | encabezado `Idempotency-Key`                                                                                                |
| Correlación de signals  | `dispatch_id`, "the identifier of the dispatch that came from the front-end SDK" | sin equivalente: Bird no acepta señales                                                                                     |
| Control de fallback     | `options.max_auto_fallbacks`, `options.force_challenge`                          | el plan de canales del país                                                                                                 |

`dispatch_id` no es un mecanismo de reintento y no corresponde junto a `Idempotency-Key`. La propia referencia de Prelude lo define como "the identifier of the dispatch that came from the front-end SDK": su SDK de Signals lo devuelve desde `dispatchSignals()`, y tú lo reenvías en el create para que su capa de fraude asocie las señales del navegador que capturó con esa verificación. Sus referencias de create y check documentan el conjunto completo de solicitudes sin clave de idempotencia ni encabezado personalizado, así que un create reintentado no queda protegido para ti. En Bird, el encabezado [`Idempotency-Key`](/docs/guides/idempotency) se encarga de eso.

Los conjuntos de canales se solapan solo parcialmente. Bird envía por email, SMS, WhatsApp y Telegram; los canales RCS, Viber, Zalo, voz y silencioso de Prelude no tienen equivalente en Bird hoy. Un número al que Prelude llegaba por Viber o Zalo recurre aquí a SMS, lo cual es una cuestión de tasa de entrega que conviene medir en el piloto en lugar de descubrir a pleno volumen.

## Mapear la llamada check

Ambos endpoints de check reciben el destinatario y el código sin ID de verificación, así que esta llamada se porta casi tal cual. La diferencia está en la respuesta:

| `status` de Prelude    | Bird                                            |
| ---------------------- | ----------------------------------------------- |
| `success`              | `success: true`                                 |
| `failure`              | `success: false`, `reason: incorrect_code`      |
| `expired_or_not_found` | `success: false`, `reason: expired` o una `404` |
| (sin valor directo)    | `success: false`, `reason: attempts_exhausted`  |

Prelude agrupa "wrong code" y "out of attempts" en `failure`; Bird los separa y devuelve `attempts_remaining` junto con ellos para que puedas mostrar al usuario cuántos intentos le quedan. Una verificación ya resuelta devuelve `404` en lugar de un estado, así que almacena la primera respuesta definitiva en vez de volver a consultar.

## Qué pasa con la capa de riesgo

La respuesta de create de Prelude reporta un veredicto de enrutamiento: un `status` de `success`, `retry`, `challenged`, `blocked` o `shadow_blocked`, con un `reason` y `risk_factors` cuando rechaza, y un `method` con el nombre del canal que eligió. La respuesta de create de Bird es la verificación en sí. No hay veredicto sobre el que ramificar, no hay objeto de signals que enviar, ni equivalente de un bloqueo en sombra, así que una integración que condiciona registros al veredicto de Prelude necesita su propia decisión antes de llamar a Bird.

Lo que Bird sí ofrece en ese ámbito es más limitado y principalmente configuración: habilitación por país para desactivar destinos que nunca atiendes, los límites de envío y verificación de la plataforma descritos en [Protecciones contra abuso](/docs/guides/verify/sending-verifications#abuse-guardrails), y el propio plan de canales. Si la protección contra bombeo fue la razón por la que elegiste Prelude, dimensiona esa diferencia antes de programar la migración.

## Mover los callbacks

Prelude envía el estado de entrega a la `callback_url` que configuras por verificación. Bird entrega a endpoints que tu espacio de trabajo registra, cada uno suscrito a los tipos de evento que le interesan, así que la URL sale del cuerpo de la solicitud. Indica los tipos de evento que tu handler necesita: `verify.verification.created`, `verify.verification.verified` y `verify.verification.failed` para la sesión, y `verify.attempt.sent`, `verify.attempt.delivered` y `verify.attempt.undelivered` para cada envío de código de verificación. No hay comodín que los sustituya. Verifica las firmas según [Standard Webhooks](https://www.standardwebhooks.com). Los payloads están en [Eventos de Verify](/docs/guides/verify/events).

## Corte de servicio

La [regla de corte](/docs/guides/verify/migrate#5-cut-over-one-code-lifetime-at-a-time) de la guía principal aplica sin cambios: un código emitido por Prelude no se puede verificar con Bird, así que cambia en la llamada create y dirige cada check al proveedor que emitió esa verificación hasta que la última expire. Como ambas APIs se indexan por el destinatario, la bifurcación es un solo condicional alrededor de tus call sites existentes, no una reescritura.

Observa la conversión durante el piloto junto con la entrega. Prelude enruta por solicitud a través de un conjunto de canales más amplio; Bird enruta según el orden de canales que configuras por país. Si la conversión de un mercado baja, reordena los canales de ese país antes de sacar conclusiones sobre la migración.

## Próximos pasos

- [Enviar verificaciones](/docs/guides/verify/sending-verifications): el contrato completo para ambas llamadas, estados y límites
- [Configuración por país](/docs/guides/verify/countries): orden de canales y disponibilidad por país
- [Remitentes y marca](/docs/guides/verify/senders): lo que el destinatario ve en cada canal
- [Eventos de Verify](/docs/guides/verify/events): los eventos a los que migra tu consumidor de callbacks

## Related resources

- [Verify phone numbers at signup](/learn/series/verify-phone-numbers-at-signup) (video)
- [What does OTP mean? One-time passwords explained](/explained/verify/what-does-otp-mean) (answer)
- [Customer verification](/verify-api) (product)
- [Build your first integration](/learn/paths/integration) (course)

[Get an implementation brief](/learn/workspace?topic=verify)
