L<highlight>API OTP</highlight> per sviluppatori che hanno bisogno che i codici arrivino.
SMS prioritario, fallback vocale in un singolo attributo, punteggio antifrode al momento dell'avvio, limiti di frequenza per destinatario. Stessa autenticazione, stessa idempotenza, stessi webhook di ogni altro canale Bird — perché lo stesso team di ingegneri li ha costruiti tutti.
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 minuti da npm install alla prima verifica
Avvia una verifica dal linguaggio che già utilizzi.
SDK in ogni runtime principale. La prima verifica va al numero di test autorizzato (+15005550006), così puoi integrare un controllo CI prima ancora di parlare con un operatore.
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();Dieci cose tra la chiamata di avvio e la schermata successiva dell'utente.
Primitive concrete, nominate e verificabili. Nessun generico "rilevamento frodi basato sull'AI".
- 01
SMS prioritario, fallback vocale in un singolo attributo
Passa fallback: "voice" all'avvio. Se l'SMS non arriva entro N secondi, effettuiamo una chiamata. Nessuna seconda integrazione.
- 02
Punteggio antifrode al momento dell'avvio
Ogni avvio restituisce un risk_score da 0 a 1. Blocca quelli ad alto rischio prima di spendere un centesimo per la consegna.
- 03
Limiti di frequenza per destinatario
Limiti configurabili per numero di telefono sui tentativi per ora e per giorno. Blocca gli attacchi brute-force a tue spese.
- 04
Instradamento basato sull'operatore
Scegliamo la rotta per operatore e per paese in tempo reale. T-Mobile US non è lo stesso canale di Reliance Jio.
- 05
Codici generati lato server
Tu non vedi mai il codice; noi non lo esponiamo mai in transito. Una superficie di rischio in meno nel tuo stack.
- 06
TTL configurabile
Default 10 minuti, intervallo 30s-1h. TTL più breve = minore superficie di frode; più lungo = migliore UX mobile.
- 07
Contatore tentativi con blocco
Numero massimo di tentativi per verifica (default 5). Dopo il blocco, il check restituisce verification_locked per una UX chiara.
- 08
OTP vocale in oltre 40 lingue
Sintetizzato al momento dell'invio, con accento corretto per locale. Stessa interfaccia bird.verifications.start — basta channel: "voice".
- 09
Webhook a ogni cambio di stato
Eventi: verification.created, verification.delivered, verification.checked, verification.expired. Stesso envelope HMAC.
- 10
Paghi solo quando il codice arriva
Nessun addebito per verification.failed. Il filtro antifrode e il rimborso per mancata consegna mantengono la spesa onesta.
Why we build Verifications
Perché i codici devono arrivare al primo tentativo, e non possiamo chiedere gentilmente agli operatori.
OTP è il canale dove ogni punto percentuale di consegna ti costa una registrazione. Gestiamo SMS da dieci anni attraverso 240 connessioni dirette con gli operatori, quindi quando un codice non arriva sappiamo se è la rotta, l'operatore, il dispositivo o il filtro antifrode — e reinstrdiamo in tempo reale. Bird Verifications è quella logica di selezione della rotta, più il punteggio antifrode, più il fallback vocale, più il contatore tentativi, esposta come due endpoint con la stessa autenticazione e lo stesso contratto webhook di ogni altro canale Bird.
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"Ogni cambio di stato è un webhook.
Payload firmati HMAC, protetti da replay, idempotenti. Lo stesso envelope su ogni canale Bird — impara uno, li hai imparati tutti.
{
"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
}
}Programmazione retry: 5s, 30s, 5m, 30m, 2h, 6h, 12h. Dead-letter dopo l'ultimo tentativo; ogni evento in dead-letter è riproducibile dalla dashboard o dall'API.
verification.createdAccettato dall'API; in procinto di essere inviato sul primo canale.verification.deliveredL'operatore ha confermato la ricezione sul dispositivo del destinatario.verification.checkedIl destinatario ha inviato un codice; il payload include approved o denied.verification.fellbackL'SMS non è arrivato nella finestra temporale; il fallback vocale è stato attivato.verification.expiredTTL scaduto senza un check riuscito.verification.lockedNumero massimo di tentativi raggiunto; le chiamate check successive restituiscono verification_locked.verification.failedErrore permanente prima dell'invio (destinatario non valido, rifiuto dell'operatore).
Se hai integrato SMS, hai integrato Verifications.
Stessa autenticazione, stessa idempotenza, stesso envelope di errore, stessa struttura webhook. La differenza è che Verifications genera il codice, sceglie la rotta, esegue il filtro antifrode e gestisce il fallback — così non devi farlo tu.
Verifications.
await bird.verifications.start({
to: "+15005550006",
channel: "sms",
fallback: "voice",
});Una chiamata. Noi scegliamo il canale, la rotta, generiamo il codice, eseguiamo il controllo antifrode, gestiamo il blocco.
SMS.
await bird.sms.send({
from: "Bird",
to: "+15005550006",
text: `Your code is ${code}.`,
});L'invio diretto, per quando vuoi gestire tu la generazione del codice e la policy di retry.