Protect logins with a second factor.
Send one-time verification codes over SMS, WhatsApp, voice, and email to confirm logins, password resets, payouts, and sensitive account changes. Bird Verify handles code generation, hashed storage, expiration timers, channel fallback, and brute-force lockouts, freeing your team from maintaining OTP database tables or debugging delayed sign-in codes.
verify.ts
200 · pendingimport { BirdClient } from "@messagebird/sdk"; const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY!, }); // Send the code, then check it by recipient. await bird.verify.verifications.create({ to: { phone_number: "+15551234567" }, }).safe(); const { data, error } = await bird.verify.verifications.check({ to: { phone_number: "+15551234567" }, code: userInput, }).safe(); if (error) throw error;
Your account
Confirm it’s you.
Enter the code sent to
+1 ••• ••• 4567
verify.ts
200 · pendingimport { BirdClient } from "@messagebird/sdk"; const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY!, }); // Send the code, then check it by recipient. await bird.verify.verifications.create({ to: { phone_number: "+15551234567" }, }).safe(); const { data, error } = await bird.verify.verifications.check({ to: { phone_number: "+15551234567" }, code: userInput, }).safe(); if (error) throw error;
Your account
Confirm it’s you.
Enter the code sent to
+1 ••• ••• 4567
verify.ts
200 · pendingimport { BirdClient } from "@messagebird/sdk"; const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY!, }); // Send the code, then check it by recipient. await bird.verify.verifications.create({ to: { phone_number: "+15551234567" }, }).safe(); const { data, error } = await bird.verify.verifications.check({ to: { phone_number: "+15551234567" }, code: userInput, }).safe(); if (error) throw error;
Your account
Confirm it’s you.
Enter the code sent to
+1 ••• ••• 4567
Verify logins and step-up actions without managing OTP state.
Building two-factor authentication in-house usually means maintaining database tables for hashed codes, expiry windows, resend cooldowns, and failed-attempt counters. With the Bird Verify API, your app sends a code when a user signs in, resets a password, or approves a payout, then checks the submitted code directly against their phone number or email address. Your session store keeps no verification IDs between steps, and the same flow supports passwordless login when the code itself is the credential.
How Bird keeps two-factor sign-ins fast and secure.
Reliable delivery across channels with built-in protection against code guessing and traffic pumping.
- 01
Trigger on password check, confirm on code entry.
Request a code as soon as the user's password passes or they start a sensitive action like a payout or email change, then verify the digits they submit. Calling the send endpoint again for a delayed code resends cleanly on the active verification without invalidating a code that is already on the way.
- 02
Reach users on SMS, WhatsApp, voice, or email.
Prevent user lockouts when carrier filtering delays an SMS or a traveler has no cellular signal. Deliver codes to a phone number over SMS, WhatsApp, or a spoken voice call, or send passcodes to an email address using your existing contact details.
- 03
Update channel routing and expiry rules without a deploy.
Configure country-specific channel order, code length, and expiration windows once in your workspace across sign-ins, password resets, and step-up checks. When a customer reports a failed login, per-verification delivery logs show which channel ran and whether the code was delivered, mistyped, or expired.
- 04
Block brute-force guessing and SMS pumping.
Enforce attempt limits that invalidate a code after repeated wrong guesses, alongside per-recipient send caps that stop attackers or bots from draining your messaging budget through repeated resend requests.
Add a second factor to your sign-in handler.
Send a verification code after validating the user's password, and check the digits when they submit the second-factor form. The check response tells your app whether the code matched, how many attempts remain on a typo, or whether the window expired so you can prompt the user clearly.
// Send the second factor once the password checks out.
await bird.verify.verifications.create({
to: { phone_number: user.phone },
}).safe();
const { data, error } = await bird.verify.verifications.check({
to: { phone_number: user.phone },
code: submitted,
}).safe();
if (error) throw error;
if (data.success) grantSession(user);
Build it on the Verify platform
Channels, fallback routing, and abuse controls for your authentication flows.
Scale without
losing control.
Organize teams in workspaces, control API access, and trace changes through audit logs.
Organization
Harbor
Access stays in its workspace.
Production/API keys
Signup service
ActiveAlex Lee
Admin
Today · UTC
Audit log
Organization
Harbor
Access stays in its workspace.
Production/API keys
Signup service
ActiveAlex Lee
Admin
Today · UTC
Audit log
Organization
Harbor
Access stays in its workspace.
Production/API keys
Signup service
ActiveAlex Lee
Admin
Today · UTC
Audit log