De OTP API voor ontwikkelaars die codes moeten laten aankomen.
SMS-first, voice-fallback in één attribuut, fraudescoring bij starttijd, snelheidslimieten per ontvanger. Dezelfde auth, dezelfde idempotentie, dezelfde webhooks als elk ander Bird-kanaal — omdat hetzelfde engineeringteam ze allemaal heeft gebouwd.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
// 1. Start the verification.
const { data: start, error: startErr } = await bird.verifications.start({
to: "+15005550006",
channel: "sms",
fallback: "voice",
expires: "10m",
}).safe();
if (startErr) throw startErr;
// → { id: "ver_8sQ91pZ4...", risk_score: 0.04, status: "pending" }
// 2. Check the code the user typed.
const { data: check, error: checkErr } = await bird.verifications.check({
id: start.id,
code: "482917",
}).safe();
if (checkErr) throw checkErr;
console.log(check.status);
// → "approved"5 minuten van npm install tot eerste verificatie
Start een verificatie vanuit de taal die u al gebruikt.
SDK's in elke grote runtime. De eerste verificatie gaat naar het goedgekeurde testnummer (+15005550006), zodat u een CI-check kunt uitrollen voordat u met een carrier praat.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.verifications.start({
to: "+15005550006",
channel: "sms",
fallback: "voice",
expires: "10m",
}).safe();Tien dingen tussen de startaanroep en het volgende scherm van de gebruiker.
Concrete bouwblokken, benoemd en auditeerbaar. Geen vaag "AI-gestuurde fraudedetectie"-verhaal.
- 01
SMS-first, voice-fallback in één attribuut
Geef fallback: "voice" mee bij start. Als SMS niet binnen N seconden aankomt, bellen we in plaats daarvan. Geen tweede integratie.
- 02
Fraudescoring bij starttijd
Elke start retourneert een risk_score van 0-1. Blokkeer de hoog-risico verzoeken voordat u een cent aan bezorging uitgeeft.
- 03
Snelheidslimieten per ontvanger
Configureerbare limieten per telefoonnummer op pogingen per uur en per dag. Blokkeert brute-force op uw kosten.
- 04
Carrier-bewuste routering
Wij kiezen de route per carrier per land in realtime. T-Mobile US is niet dezelfde verbinding als Reliance Jio.
- 05
Codes worden server-side gegenereerd
U ziet de code nooit; wij sturen hem nooit onbeschermd over de lijn. Eén minder lekoppervlak in uw stack.
- 06
Configureerbare TTL
Standaard 10 minuten, bereik 30s-1u. Kortere TTL = kleiner fraudeoppervlak; langer = betere mobiele UX.
- 07
Pogingsteller met lockout
Maximaal aantal pogingen per verificatie (standaard 5). Na lockout retourneert check verification_locked voor een duidelijke UX.
- 08
Voice OTP in meer dan 40 talen
Gesynthetiseerd op het moment van verzending, met correct accent per locale. Hetzelfde bird.verifications.start-oppervlak — alleen channel: "voice".
- 09
Webhook bij elke statuswijziging
Events: verification.created, verification.delivered, verification.checked, verification.expired. Dezelfde HMAC-envelope.
- 10
Betaal alleen als de code aankomt
Geen kosten voor verification.failed. Het fraudescorefilter en de niet-bezorgd-restitutie houden de uitgaven eerlijk.
Why we build Verifications
Omdat codes bij de eerste poging moeten aankomen, en we carriers niet beleefd kunnen vragen.
OTP is het kanaal waar elk procent bezorging u een aanmelding kost. We versturen al tien jaar SMS via 240 directe carrierverbindingen, dus als een code niet aankomt weten we of het de route, de carrier, het toestel of het fraudefilter is — en we routeren er in realtime omheen. Bird Verifications is die routeselectielogica, plus de fraudescore, plus de voice-fallback, plus de pogingsteller, beschikbaar als twee endpoints met hetzelfde auth- en webhookcontract als elk ander Bird-kanaal.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
// 1. Start the verification.
const { data: start, error: startErr } = await bird.verifications.start({
to: "+15005550006",
channel: "sms",
fallback: "voice",
expires: "10m",
}).safe();
if (startErr) throw startErr;
// → { id: "ver_8sQ91pZ4...", risk_score: 0.04, status: "pending" }
// 2. Check the code the user typed.
const { data: check, error: checkErr } = await bird.verifications.check({
id: start.id,
code: "482917",
}).safe();
if (checkErr) throw checkErr;
console.log(check.status);
// → "approved"Elke statuswijziging is een webhook.
HMAC-ondertekende payloads, replay-beschermd, idempotent. Dezelfde envelope op elk Bird-kanaal — leer er één, en u kent ze allemaal.
{
"type": "verification.delivered",
"id": "evt_5kQ81y...",
"created_at": "2026-05-19T15:42:01.221Z",
"data": {
"verification_id": "ver_8sQ91pZ4",
"to": "+15005550006",
"channel": "sms",
"carrier": "T-Mobile USA",
"risk_score": 0.04,
"latency_ms": 1421
}
}Retry-schema: 5s, 30s, 5m, 30m, 2u, 6u, 12u. Dead-letter na de laatste poging; elk dead-lettered event is opnieuw afspeelbaar via het dashboard of de API.
verification.createdGeaccepteerd door de API; staat op het punt te verzenden via het eerste kanaal.verification.deliveredCarrier heeft ontvangst op het toestel van de ontvanger bevestigd.verification.checkedDe ontvanger heeft een code ingevoerd; payload bevat approved of denied.verification.fellbackSMS kwam niet aan binnen het tijdsvenster; de voice-fallback is verzonden.verification.expiredTTL verstreken zonder succesvolle check.verification.lockedMaximaal aantal pogingen bereikt; verdere check-aanroepen retourneren verification_locked.verification.failedPermanente fout vóór verzending (ongeldige ontvanger, carrier-weigering).
Als u SMS hebt geïntegreerd, hebt u Verifications geïntegreerd.
Dezelfde auth, dezelfde idempotentie, dezelfde error-envelope, dezelfde webhookstructuur. Het verschil is dat Verifications de code genereert, de route kiest, het fraudefilter uitvoert en de fallback afhandelt — zodat u dat niet hoeft te doen.
Verifications.
await bird.verifications.start({
to: "+15005550006",
channel: "sms",
fallback: "voice",
});Eén aanroep. Wij kiezen het kanaal, de route, genereren de code, voeren de fraudecheck uit en handelen de lockout af.
SMS.
await bird.sms.send({
from: "Bird",
to: "+15005550006",
text: `Your code is ${code}.`,
});De ruwe verzending, voor wanneer u zelf de codegeneratie en het retrybeleid wilt beheren.