Sign inGet started

Migrate Verify from Twilio

This page maps Twilio Verify v2 to Bird Verify. Follow the main migration guide in order and use these mappings for steps 1 and 3.
The Service is the piece with no counterpart. Twilio addresses POST https://verify.twilio.com/v2/Services/{ServiceSid}/Verifications, and the Service holds code length, TTL, lookup, landline handling, and rate limits. Bird addresses POST /v1/verify/verifications with no service segment: those settings belong to your workspace rather than an ID in the path. Multiple Service IDs have no equivalent within a workspace, and you cannot select a configuration per request.

Hand this to your agent

Paste this into Claude Code, Cursor, or Codex. The agent works through this page against your own repository, using whichever Bird surface it already has: the MCP server if one is connected, the CLI if it is installed and signed in.
Esempio di codice
I am moving a phone verification integration from Twilio Verify 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/twilio.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 Twilio Verify usage in this repository before you change anything: the Verifications and VerificationCheck call sites, every Service SID they name and what each Service is configured with, and any place I read a verification status. Bird has no Service segment and no per-request configuration selection, so tell me if I use more than one Service and what differs between them.
4. Tell me early which of these I depend on, because none of them carries over and I would rather know now than at the end. 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 takes no per-request template, locale or message body, and Bird owns the sender identity, so the message my users see will change on cutover. Twilio's Service holds code length, TTL, lookup, landline handling and rate limits; on Bird those belong to the workspace rather than to an ID in the path, so tell me which of my Service settings have no home.
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 Twilio Verify cannot be checked by Bird and a code issued by Bird cannot be checked by Twilio Verify. 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 Twilio Verify path is a separate step: ask me again and wait for me to reply with the words retire the Twilio Verify 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.

Map the create call

What it doesTwilio VerifyBird
RecipientToto.phone_number or to.email
ChannelChanneloptions.channels, else the country's configured order
Code lengthService CodeLengthoptions.code_length, else the workspace default
Code lifetimeService TTLthe workspace Duration setting
Attempt limitService max attemptsthe workspace Maximum Retries setting
CorrelationTagsmetadata
Safe retries(none)Idempotency-Key header
Custom passcodeCustomCodeno equivalent
LocalizationLocaleno equivalent
Message contentTemplateSid, CustomFriendlyName, ChannelConfigurationno equivalent, apart from a branded email sender
Per-key throttlesRateLimitsfixed platform guardrails
Fraud controlsRiskCheck, Fraud Guard, DeviceIpnot exposed on the API
SMS autofillAppHashno equivalent
PSD2Amount, Payeeno equivalent
The channels do not line up one to one either:
Twilio ChannelBird
smssms
emailemail
whatsappwhatsapp
callno equivalent
sna, autono equivalent
rcsno equivalent
(none)telegram, available for numbers registered with Telegram
A flow that uses call as the accessibility fallback, or sna and auto for a codeless path, needs rethinking before you commit to a date. Everything else is a channel-order change on the Countries page rather than a per-request parameter.

Map the check call

Twilio's POST /v2/Services/{ServiceSid}/VerificationCheck takes To or VerificationSid, plus Code. Bird's POST /v1/verify/verifications/check takes only the recipient and the code, so the VerificationSid path disappears along with the column you stored it in. Supply exactly the address set you created the verification with.
The result shape differs where it matters most:
  • Twilio answers with a status field; Bird answers with a boolean. success: true means verified. success: false carries a reason of incorrect_code, expired, or attempts_exhausted, plus attempts_remaining, so the "how many tries left" figure you may be counting yourself comes back on the response.
  • Both go to 404 once the verification is spent. Twilio deletes the verification when it is approved, expired, or out of attempts; Bird stops accepting checks in any final state. Store the first definitive answer rather than re-checking.

Translate statuses

Twilio statusBird statusBird reason
pendingpendingnone
approvedverifiednone
max_attempts_reachedfailedattempts_exhausted
expiredexpiredttl_elapsed
canceledno equivalent: a verification is not cancellable
There is no update endpoint, so the Twilio pattern of forcing a verification to approved or canceled from your backend has no counterpart. A verification ends when the user verifies it, exhausts the attempts, or lets it expire.

Move the event stream

Twilio Verify reports activity through Event Streams: a sink plus a subscription to verification status events, configured outside the Verify API. Bird uses the same webhook mechanism as every other channel. Subscribe an endpoint to verify.verification.* for session events and verify.attempt.* for individual passcode deliveries, and verify the signature per Standard Webhooks. See Verify events.
The two axes matter when you port dashboards. Twilio's verification status events line up with Bird's session events, and Bird's attempt events add per-send delivery outcomes on the same session, including the sends that a resend or a channel failover produces.

Cut over

The cutover rule in the main guide is the one to plan around: a code issued by Twilio cannot be checked by Bird, so switch at the create call and keep routing checks to whichever provider issued the verification until the last Twilio code expires.
Also budget for the sender change. Twilio Verify delivers under your Service's friendly name and your own sender pool; Bird delivers under one of its own managed identities, Bird Verify or Authifly, on email, SMS, and WhatsApp, with your own domain available for the email channel. Users mid-signup see a different sender, and support scripts that say "look for a text from us" need updating.

Next steps