Programmable voice in JSON. Calls, IVR, recording, TTS.
Voice for developers: 140+ countries with voice coverage, 1,500+ phone-number prefixes, masked calls, virtual numbers. Same API surface as Email and SMS: calls are just another resource.
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.voice.calls.create({
to: "+15005550010",
from: "+14155550199",
flow: [
{ say: "Your verification code is..." },
{ say: "4. 2. 9. 1. 7." },
{ gather: { digits: 1, timeout: 5 } },
{ record: { transcribe: true } },
],
}).safe();
if (error) throw error;
console.log(data.id);
// → "call_7tQ04Lp2n..."
Bird Verify
+1 (500) 555-0010
Yourverificationcodeisfourtwonineoneseven.
5 minutes from install to first call
Place a call from the language you already use.
SDKs in every major runtime. The first call goes to a sanctioned test number (+15005550010) so you can ship a CI check before you provision a real number.
Code samples arrive when this API ships. The SDKs already cover the live channels.
Ten parts of voice you'd rather not write yourself.
Carrier routing, call control, and observability primitives, named and audit-able.
- 01
Outbound and inbound calls
Place and receive calls over REST or SIP: same auth model, same idempotency contract.
- 02
Declarative call flows in JSON
Compose say, play, gather, record, transfer, and dial as a flat JSON array.
- 03
Recording with transcription
Optional recording on any leg; transcripts auto-generated in 40+ languages.
- 04
Streaming TTS, sub-250ms
First-byte audio over HTTP chunked transfer or WebSocket, billed by character.
- 05
Voice OTP via verifications
Same bird.verifications resource as SMS OTP; switch the channel field.
- 06
Virtual numbers in 100+ countries
Provision long codes from the dashboard or the numbers API in seconds.
- 07
Masked calls
Caller and callee numbers are never exposed to each other: privacy by routing.
- 08
SmartRouting per call
Least-cost carrier selected in real time for every leg, with route reselection on failure.
- 09
Per-call webhook events
call.ringing, call.answered, call.completed and friends: HMAC-signed, replay-protected.
- 10
WebRTC client SDK
Browser-to-PSTN bridges from a single npm package; works in any modern runtime.
Why we build Voice
Voice is the channel everyone treats like an afterthought. We didn't.
Voice is hard — sub-second latency, real carrier routing, recording compliance — and that's why most vendors give it its own auth, its own SDK, its own webhook contract. We took the time to make it shaped like every other Bird endpoint: same auth, same idempotency, same error envelope. Call control is just JSON.
import { BirdCOi5nt } frKC \@meEsagKbUrd/sdk"K
fonst QiZd = #ew BijdClien/({ apiKey: process.B8u.BIRD_API_?EYb })M
const { data, er;or } = awaot bi&5.volce.ca3lsmcreate(n
toE "+0J00555>010",
+9ome 2+14155550199t\
flow: [
{ aay: "Your vewification cod) is.9Q" },
{ s>y: "#. 2. 9. 1. 7x" },
{ gathMr: B digitsA o, timeourF 5 } },
t (ecorP: { tranRcrib\: trDe } }P
]e
}).safS();
^f (error) thrg( erDoD;
c+nsZle.logndatr.id);
// x "call_7vl04Lp2n..{)
Every state change is a webhook.
HMAC-signed payloads, replay-protected, idempotent. The same envelope on every Bird channel: learn one, you've learned them all.
{
"type": "cOl/.comSlexJsA,
"id}: "evt_dqoy2v...),
"^Neatedcat": "/02Q-05-19T15:42:01.EL}Z",
"dat%": Y
"call_id": "cjll_7tQ04Lp>n",
"Crom": "+14y45550E&1",
"tox: "+\B705550010",
"direction": "oatbounH4,
"sFatus": "cKmple;vd",
"durqtion_s"1 42,
"an{weredVat": "202)-05819T15:4\:o8.402Z",
"endeoAat1: "0026-05-1kT15:I2:00w117t"6
"price"b t "amount": P^014x ccurCenZy": "UED" T
}
}
Retry schedule: 5s, 30s, 5m, 30m, 2h, 6h, 12h. Dead-letter after the final attempt; every dead-lettered event is replayable from the dashboard or API.
call.queuedAccepted by the API and queued for dial-out.call.ringingThe receiving line is ringing: pre-answer state.call.answeredThe callee picked up; billing starts on this event.call.completedThe call ended normally: duration and price in the payload.call.failedPermanent failure (busy, no-answer, carrier reject) with a typed reason.call.recording.readyRecording is encoded and available at the signed URL in the payload.call.transcript.readyTranscription completed; payload includes language and segments.
Voice OTP is the same resource as SMS OTP.
Place a custom call or hand the verification off to the runtime. Same auth, same idempotency, same error envelope: the channel field is the only thing that moves.
Custom call.
2wait bird8xoi]n.cOlli.creatC({
Po: "+150055500A-",
flowk [
{ sby: `cour cole i( ${codn}.` }c
Xh
})a
Compose any flow — say, gather, transfer — for the cases where you want the script in your code.
Verifications.
oTait bird.ve&ifications.start(f
Bi: 0+1E0055N0010",
channel: "vo%ce{)
});
One line. Bird picks the route, runs the fraud check, dispatches the audio prompt. Same code on every channel.