Voice is being upgraded

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.

place-call.ts
201 · 0.4s
import { BirdClient } from "@bird/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..."

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.

1
2
3
4
5
6
7
8
9
import { BirdClient } from "@bird/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: "Hello from Node." }],
}).safe();

Ten parts of voice you'd rather not write yourself.

Carrier routing, call control, and observability primitives — named and audit-able.

  1. 01

    Outbound and inbound calls

    Place and receive calls over REST or SIP — same auth model, same idempotency contract.

  2. 02

    Declarative call flows in JSON

    Compose say, play, gather, record, transfer, and dial as a flat JSON array.

  3. 03

    Recording with transcription

    Optional recording on any leg; transcripts auto-generated in 40+ languages.

  4. 04

    Streaming TTS, sub-250ms

    First-byte audio over HTTP chunked transfer or WebSocket — billed by character.

  5. 05

    Voice OTP via verifications

    Same bird.verifications resource as SMS OTP; switch the channel field.

  6. 06

    Virtual numbers in 100+ countries

    Provision long codes from the dashboard or the numbers API in seconds.

  7. 07

    Masked calls

    Caller and callee numbers are never exposed to each other — privacy by routing.

  8. 08

    SmartRouting per call

    Least-cost carrier selected in real time for every leg, with route reselection on failure.

  9. 09

    Per-call webhook events

    call.ringing, call.answered, call.completed and friends — HMAC-signed, replay-protected.

  10. 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.

place-call.ts
201 · 0.4s
import { BirdClient } from "@bird/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..."

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.

POST /webhooks/bird
signed
{
  "type": "call.completed",
  "id":   "evt_8qC42v...",
  "created_at": "2026-05-19T15:42:01.221Z",
  "data": {
    "call_id":    "call_7tQ04Lp2n",
    "from":       "+14155550199",
    "to":         "+15005550010",
    "direction":  "outbound",
    "status":     "completed",
    "duration_s": 42,
    "answered_at": "2026-05-19T15:41:18.402Z",
    "ended_at":    "2026-05-19T15:42:00.117Z",
    "price":       { "amount": 0.014, "currency": "USD" }
  }
}

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.

voice.calls.create
await bird.voice.calls.create({
  to:   "+15005550010",
  flow: [
    { say: `Your code is ${code}.` },
  ],
});

Compose any flow — say, gather, transfer — for the cases where you want the script in your code.

Verifications.

verifications.start
await bird.verifications.start({
  to:      "+15005550010",
  channel: "voice",
});

One line. Bird picks the route, runs the fraud check, dispatches the audio prompt. Same code on every channel.

Per-minute, country-dependent.

Streaming TTS billed by character. Volume discounts auto-apply at common thresholds. No seat fee, no tier features locked behind annual commits.

Start with one channel.
Add the others when you're ready.

A test API key is yours immediately. Production unlocks when you add a payment method and verify a sender.

Get startedRead docsor

Using Claude Code, Cursor, or Codex? Point it at our hosted MCP server: curated Bird tools, a browser sign-in, and no API key. Or install the bird-ai plugin.

Cursor