# Verify migreren vanuit Prelude

Deze pagina vertaalt Prelude's v2-verificatie-API naar Bird Verify. Volg de [hoofdmigratiegids](/docs/guides/verify/migrate) op volgorde en gebruik deze vertalingen voor stap 1 en 3.

De structuren lijken sterk op elkaar. Prelude's `POST https://api.prelude.dev/v2/verification` en `POST /v2/verification/check` zijn een bearer-geauthenticeerd create-en-check-paar dat op de ontvanger sleutelt in plaats van op een verificatie-ID, en dat geldt ook voor [`POST /v1/verify/verifications`](/docs/api/reference/create-verification) en [`POST /v1/verify/verifications/check`](/docs/api/reference/create-verification-check). Een nieuwe create-aanroep voor een actieve ontvanger probeert opnieuw in plaats van een nieuwe verificatie te starten, op beide platformen. Wat niet meekomt is de risicolaag: Prelude's signals, routeringsuitspraken en stille verificatie hebben geen tegenhanger in de Bird Verify API.

## Geef dit aan je agent

Plak dit in Claude Code, Cursor of Codex. De agent werkt deze pagina door tegen je eigen repository, met welk Bird-oppervlak die al heeft: de MCP-server als er een verbonden is, de CLI als die geïnstalleerd is en je bent ingelogd.

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

## Vertaal de create-aanroep

| Wat het doet               | Prelude                                                                          | Bird                                                                                                            |
| -------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Ontvanger                  | `target.type` + `target.value`                                                   | `to.phone_number` of `to.email`                                                                                 |
| Codelengte                 | `options.code_size`                                                              | `options.code_length`                                                                                           |
| Kanaalvoorkeur             | `options.preferred_channel`, `options.channels`                                  | `options.channels`, anders de geconfigureerde volgorde van het land                                             |
| Correlatie                 | `metadata.correlation_id`                                                        | `metadata`                                                                                                      |
| Bezorgcallbacks            | `options.callback_url`                                                           | een werkruimte-webhook die is geabonneerd op de verify-eventtypen die je opgeeft                                |
| Aangepaste verificatiecode | `options.custom_code`                                                            | geen equivalent                                                                                                 |
| Lokalisatie                | `options.locale`                                                                 | `options.language`                                                                                              |
| Afzenderidentiteit         | `options.sender_id`                                                              | selecteer een door Bird beheerde of eigen afzender per kanaal of land, niet per verzoek                         |
| Berichttemplate            | `options.template_id`, `options.variables`                                       | geen equivalent per verzoek; selecteer een goedgekeurd WhatsApp-authenticatietemplate in de Verify-configuratie |
| Android autofill           | `options.app_realm`                                                              | geen equivalent                                                                                                 |
| Risicosignalen             | `signals` (IP, device, fingerprint)                                              | niet geaccepteerd                                                                                               |
| Veilig opnieuw proberen    | geen idempotency-key of -header in hun create- of check-referentie               | `Idempotency-Key`-header                                                                                        |
| Signalscorrelatie          | `dispatch_id`, "the identifier of the dispatch that came from the front-end SDK" | geen equivalent: Bird accepteert geen signals                                                                   |
| Fallback-beheer            | `options.max_auto_fallbacks`, `options.force_challenge`                          | het kanaalplan van het land                                                                                     |

`dispatch_id` is geen retry-mechanisme en hoort niet naast `Idempotency-Key`. Prelude's eigen referentie definieert het als "the identifier of the dispatch that came from the front-end SDK": hun Signals SDK retourneert het vanuit `dispatchSignals()`, en je stuurt het mee op de create zodat hun fraudelaag de browsersignalen die het vastlegde kan koppelen aan die verificatie. Hun create- en check-referenties documenteren de volledige requestset zonder idempotency-key en zonder aangepaste header, dus een herhaalde create is niet veilig voor je. Op Bird doet de [`Idempotency-Key`](/docs/guides/idempotency)-header dat wel.

De kanaalsets overlappen maar gedeeltelijk. Bird bezorgt via e-mail, SMS, WhatsApp en Telegram; Prelude's RCS, Viber, Zalo, voice en stille kanalen hebben geen Bird-equivalent. Een nummer dat Prelude via Viber of Zalo bereikte valt hier terug op SMS, wat een bezorgpercentagevraag is die je beter in de pilot kunt meten dan bij vol volume ontdekken.

## Vertaal de check-aanroep

Beide check-endpoints nemen de ontvanger en de code zonder verificatie-ID, dus deze aanroep is bijna één op één over te zetten. Het verschil zit in het antwoord:

| Prelude `status`       | Bird                                             |
| ---------------------- | ------------------------------------------------ |
| `success`              | `success: true`                                  |
| `failure`              | `success: false`, `reason: incorrect_code`       |
| `expired_or_not_found` | `success: false`, `reason: expired` of een `404` |
| (geen directe waarde)  | `success: false`, `reason: attempts_exhausted`   |

Prelude combineert "wrong code" en "out of attempts" in `failure`; Bird scheidt ze, en retourneert `attempts_remaining` erbij zodat je de gebruiker kunt tonen hoeveel pogingen er nog over zijn. Een verificatie die al is afgerond retourneert `404` in plaats van een status, dus sla het eerste definitieve antwoord op in plaats van opnieuw te checken.

## Wat er met de risicolaag gebeurt

Prelude's create-antwoord rapporteert een routeringsuitspraak: een `status` van `success`, `retry`, `challenged`, `blocked` of `shadow_blocked`, met een `reason` en `risk_factors` wanneer het weigert, en een `method` die het gekozen kanaal noemt. Het create-antwoord van Bird is de verificatie zelf. Er is geen uitspraak om op te vertakken, geen signals-object om te verzenden en geen equivalent van een shadow block, dus een integratie die aanmeldingen afschermt op basis van Prelude's uitspraak heeft een eigen beslissing nodig voordat ze Bird aanroept.

Wat Bird uit die ruimte meeneemt is beperkter en grotendeels configuratie: per-land-activering om bestemmingen die je nooit bedient uit te schakelen, de platformlimieten voor verzenden en checken beschreven in [Misbruikbeveiligingen](/docs/guides/verify/sending-verifications#abuse-guardrails), en het kanaalplan zelf. Als pumpingbescherming de reden was dat je voor Prelude koos, schat dat verschil in voordat je de migratie plant.

## Verplaats de callbacks

Prelude post bezorgstatussen naar de `callback_url` die je per verificatie instelt. Bird bezorgt aan endpoints die je werkruimte registreert, elk geabonneerd op de gewenste eventtypen, zodat de URL uit de requestbody verdwijnt. Geef de eventtypen op die je handler wil: `verify.verification.created`, `verify.verification.verified` en `verify.verification.failed` voor de sessie, en `verify.attempt.sent`, `verify.attempt.delivered` en `verify.attempt.undelivered` voor elke verificatiecodeverzending. Er is geen wildcard die ze vervangt. Verifieer handtekeningen volgens [Standard Webhooks](https://www.standardwebhooks.com). De payloads staan in [Verify events](/docs/guides/verify/events).

## Overschakelen

De [overschakelregel](/docs/guides/verify/migrate#5-cut-over-one-code-lifetime-at-a-time) in de hoofdgids geldt ongewijzigd: een code die Prelude uitgaf kan niet door Bird worden gecheckt, dus schakel over bij de create-aanroep en routeer elke check naar de provider die die verificatie uitgaf totdat de laatste is verlopen. Omdat beide API's op de ontvanger sleutelen, is de vertakking één enkele conditional rond je bestaande aanroeppunten in plaats van een herschrijving.

Houd tijdens de pilot conversie én bezorging in de gaten. Prelude routeert per request over een bredere kanaalset; Bird routeert op de kanaalvolgorde die je per land instelt. Als de conversie van een markt daalt, wijzig dan eerst de kanaalvolgorde van dat land voordat je conclusies trekt over de migratie.

## Volgende stappen

- [Verificaties verzenden](/docs/guides/verify/sending-verifications): het volledige contract voor beide aanroepen, statussen en limieten
- [Landconfiguratie](/docs/guides/verify/countries): kanaalvolgorde en beschikbaarheid per land
- [Afzenders en branding](/docs/guides/verify/senders): wat de ontvanger ziet op elk kanaal
- [Verify events](/docs/guides/verify/events): de events waar je callback-consumer naartoe migreert

## 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)
