Channel orchestration
In previewStart from our defaults. Override only what you need.
Channel availability, sender rules, and regulations differ by country, and getting them right is years of work. Bird ships that as a per-country base configuration: which channels land where, which senders are allowed, and sane code defaults. Your settings layer on top. You change one thing for one country; everything you don't touch falls through to the layer below. That's per-country routing as a first-class API resource, the control most verification APIs don't give you.
import { 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 } = await bird.verify.verifications.check({
to: { phone_number: "+15551234567" },
code: userInput,
}).safe();You inherit Bird's defaults, then build on them.
Every verification on the Bird Verify API resolves its settings through a cascade. At the bottom is a per-country base Bird maintains from years of running email and SMS — so before you configure anything, a verification already routes sensibly in every country. Your configuration and per-country overrides layer on top, and a per-request option can tune a single call. You're never starting from a blank slate, and you only own the decisions you actually want to make.
The value cascade.
The highest tier that sets a value wins; anything you leave unset falls through to the tier below.
- 01
Per-request options.
Fields on the create call (code length, channel preference, locale) win for that one verification. The lightest, most local override.
- 02
Your per-country overrides.
Change the channel order or a sender for one country. An override merges: it touches the fields you set, and the rest of that country still inherits from below.
- 03
Your configuration defaults.
Your app-wide plan and code rules — the channel order, code length, TTL, and attempts you want everywhere you haven't set a country override.
- 04
Bird's per-country base.
The bottom layer: Bird's own per-country defaults, drawn from running email and SMS at scale. Whatever you leave unset falls through to this, so a verification always resolves to a sensible plan.
Override a country, inherit the rest.
Set your plan once, then touch only the countries that need something different. Here Brazil leads with WhatsApp, then SMS; every other country keeps falling through to your defaults and Bird's base.
// Your app-wide default plan.
await bird.verify.verifications.configurations.update("vfc_login", {
channels: [
{ channel: "email", state: "enabled" },
{ channel: "sms", state: "enabled" },
],
}).safe();
// Override one country; the rest inherits.
await bird.verify.verifications.configurations.countries.upsert("vfc_login", "BR", {
channels: [
{ channel: "whatsapp", state: "enabled" },
{ channel: "sms", state: "enabled" },
],
}).safe();What a verification resolves to.
A Brazilian number under this configuration resolves through the cascade. The BR override orders WhatsApp then SMS, both are available, and the verification reports the ordered plan it will use, with its typed vrf_ id.
const { data } = await bird.verify.verifications.create({
configuration_id: "vfc_login",
to: { phone_number: "+5511998765432" }, // Brazil
}).safe();
// Resolved through the cascade + availability/kill-switch ceilings:
// {
// id: "vrf_01k2m9q8e7fh3v0b7m4d2a9xzt",
// status: "pending",
// channels: [{ channel: "whatsapp" }, { channel: "sms" }],
// last_channel: "whatsapp"
// }Two ceilings sit above the cascade.
The cascade decides defaults. Two gates decide what's allowed — they cap the resolved plan rather than supplying values that fall through:
Per-country availability. You can only enable channels Bird actually offers in a country. Enabling one we don't support there is a no-op, not a silent failure — availability is an intersection, never an override.
Global kill-switch. When a provider has an incident, Bird can pull a channel everywhere at once. Your configuration isn't touched; the resolved plan simply falls back to the next channel, then restores when the switch clears.
Routing you set, not a ticket you file.
Resolved per verification, returned on the response.
- 01
Per-country routes, by the number.
The country is derived from the recipient's E.164 number — you don't pass it. Set a route for a country and it overrides the order and senders there.
- 02
Turn channels on and off.
Each channel carries an enable/disable state, so you can switch one off for a country without losing its place in the plan.
- 03
The resolved plan is on the response.
Every verification reports the ordered channels it resolved to, so what the cascade decided is never a mystery.
- 04
Automatic failover is rolling out.
Delivery-driven advancement through the plan (trying the next channel when one doesn't land) is rolling out as delivery status lands. The plan is already resolved and returned today.
Channel orchestration FAQ
What is the configuration cascade?+
What does Bird's per-country base give me?+
Does a per-country override replace the whole plan?+
Can I enable a channel Bird doesn't offer in a country?+
How is the country determined?+
Who do my users see the code from?+
The rest of the Verify platform
One API, one set of keys. Explore the other capabilities.
The per-country control no other verification API gives you.
Orchestration is one capability of Bird Verify: the channels, the code, and the limits ship with it, on the same two endpoints.