Create a verification
/v1/verify/verificationsconst verification = await bird.verify.verifications.create({
to: { phone_number: "+15551234567" },
});
console.log(verification.id, verification.status);verification = client.verify.verifications.create(to={"phone_number": "+15551234567"})
print(verification.id, verification.status)verification, err := client.Verify.Verifications.Create(context.Background(), bird.VerifyVerificationsCreateParams{
To: bird.VerificationTo{PhoneNumber: bird.String("+15551234567")},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(verification.Id, *verification.Status)$verification = $bird->verify->verifications->create(
(new VerificationCreateRequest())->setTo((new VerificationTo())->setPhoneNumber('+15551234567')),
);
echo $verification->getId(), ' ', $verification->getStatus();bird verify verifications create --body-file - <<'JSON'
{
"to": {
"phone_number": "+15551234567"
},
"metadata": {
"correlation_id": "signup-7f3a"
}
}
JSONcurl -X POST "https://us1.platform.bird.com/v1/verify/verifications" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": {
"phone_number": "+15551234567"
},
"metadata": {
"correlation_id": "signup-7f3a"
}
}'{
"id": "vrf_01krdgeqcxet5s7t44vh8rt9mg",
"status": "pending",
"reason": null,
"to": {
"email": "user@example.com"
},
"channels": [
{
"channel": "email"
}
],
"last_channel": "email",
"expires_at": "2026-05-20T09:24:52Z",
"created_at": "2026-05-20T09:14:52Z",
"updated_at": "2026-05-20T09:14:52Z"
}
Creates a verification and sends the recipient a one-time passcode. Provide an email address, a phone number, or both in to. The service sends over one channel at a time and moves to the next planned channel if delivery fails.
Calling this again for the same recipient reuses the verification in progress. During the resend cooldown, it returns the current state without sending, so nothing is charged and no send budget is spent. After the cooldown, it sends a fresh passcode, and that send draws on the recipient's hourly send cap exactly as a new verification does, so repeated resends can exhaust the cap and return 429 for the rest of that rolling hour. Abuse guardrails gives the figures.
The 200 response contains the current state, never the passcode. Submit the recipient's passcode with Check a verification before expires_at. An invalid recipient returns 422; exceeding the send rate limit returns 429.
Request Payload
toThe recipient to verify. Provide an email, a phone_number, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
Show child parameters
to.emailThe recipient's email address. Case does not matter; the address is lowercased before use.
to.phone_numberThe recipient's phone number in E.164 format, with the leading + and country code (for example +15551234567). A number in any other format is rejected as an invalid recipient (422).
optionsPer-request overrides applied to this verification only.
Show child parameters
options.code_lengthPasscode length for this verification. Omit to use the configured length.
options.channelsReorder or narrow the delivery channels for this request. List channel names in the order to try them; a channel you omit is not used for this request, and a channel not already enabled for the recipient is ignored. A list that leaves no usable channel fails the request with 422. Omit the field to use the configured order.
options.languageWhich of the built-in message translations to send. It applies to SMS, email and WhatsApp, and has no effect on a Telegram verification. A tag with no translation of its own falls back to its base language, and then to English. The attempt's template_language reports which translation was used. The tag is fixed for the verification, so a resend arrives in the same language as the first message.
Omit it and the language is read from the recipient phone number's country, so a French number gets French without you asking. Set it to override that. A verification with no phone number, and one whose country has no translation here, sends English.
Supported: en, ar, bg, cs, da, de, el, es, fi, fr, he, hi, hr, hu, id, it, ja, ko, lt, lv, mk, mn, ms, nb-NO, nl, no, pl, pt, ro, ru, sk, sl, sr, sv, th, tr, uk, vi, zh, zh-TW. Every one of them is available on SMS and email. Mongolian (mn) is the one WhatsApp cannot carry, so a WhatsApp passcode falls back to English for it.
metadataOptional key/value pairs to attach to the verification, for example a correlation id. Returned on the verification.
Response Payload
idstatusThe verification's current state:
pending: Awaiting a correct passcode.verified: A correct passcode was submitted.failed: The verification cannot be completed. Either too many incorrect passcodes were submitted, or no planned channel could deliver one. Readreasonto tell those apart.expired: The validity window elapsed before a correct passcode.canceled: The verification was canceled before completion.blocked: A fraud or abuse control stopped the verification.
Possible values: pending, verified, failed, expired, canceled, blocked
reasonWhy the verification reached its final state, or null while pending and once verified. See the enum for the values it can take.
toThe recipient to verify. Provide an email, a phone_number, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
Show child attributes
to.emailThe recipient's email address. Case does not matter; the address is lowercased before use.
to.phone_numberThe recipient's phone number in E.164 format, with the leading + and country code (for example +15551234567). A number in any other format is rejected as an invalid recipient (422).
channelsThe channels this verification uses to deliver the passcode, in attempt order: the first entry is tried first and later entries are fallbacks. An email recipient is verified over email; a phone recipient is verified over the phone channels enabled for its destination country, in the order that country's configuration sets.
Show child attributes
channels.channelThe channel a passcode is delivered over. Open enum: new channels may be added over time, so treat any unrecognized value as a future channel rather than an error.
Possible values (may grow over time): email, sms, whatsapp, telegram, voice
last_channelThe channel the most recent passcode was sent on, or null before the first send. Open enum; new channels may be added over time, so treat any unrecognized value as a future channel rather than an error.
Possible values (may grow over time): email, sms, whatsapp, telegram, voice
metadataThe key/value pairs attached when the verification was created.
expires_atWhen the verification expires if no correct passcode is submitted first. After this time its status reports expired.
verified_atWhen the verification was completed, or null if it is not yet verified.
created_atupdated_atRelated resources
Continue with the documentation, guides and examples for this topic.