WhatsApp is being upgraded

The WhatsApp Business API, without the BSP runaround.

Official Meta Business Solution Provider since the API existed. Template approval, session windows, media, interactive messages — all handled. Two billion-plus monthly WhatsApp users, addressable from a single endpoint that looks like every other Bird channel.

order-shipped.ts
200 · 480ms
import { BirdClient } from "@bird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

const { data, error } = await bird.whatsapp.send({
  to:       "+15005550009",
  template: "order_shipped",
  locale:   "en_US",
  variables: {
    customer_name:   "Ada",
    order_id:        "BRD-49217",
    tracking_url:    "https://track.bird.dev/49217",
    eta:             "Thursday, May 21",
  },
}).safe();

if (error) throw error;
console.log(data.id);
// → "wa_msg_8nB91Yk3p..."

5 minutes from npm install to first send

Send a WhatsApp from the language you already use.

SDKs in every major runtime. The first send goes to a sanctioned test recipient (+15005550009) with a pre-approved template, so you can ship a CI check before you submit your first template for approval.

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.whatsapp.send({
  to:       "+15005550009",
  template: "hello_world",
  locale:   "en_US",
}).safe();

Ten things the BSP gate hides from you. We don't.

WhatsApp is gated by Meta. The choice of BSP is whether the gates show up in your code or get smuggled into a dashboard. We chose code.

  1. 01

    Official Meta Business Solution Provider (BSP)

    Direct relationship with Meta since the API existed. No resold transit, no third-party hop.

  2. 02

    Template management

    Submit, track approval state, and get a webhook the moment Meta approves or rejects.

  3. 03

    Session-window awareness

    The SDK tells you whether free-form or template is allowed before you send.

  4. 04

    Interactive messages

    Buttons, lists, product cards, and WhatsApp Flows — declared in the same payload.

  5. 05

    Media and rich content

    Images, video, documents, location, contacts, link previews, reactions, and replies.

  6. 06

    WhatsApp Flows

    Multi-step in-app forms with backend validation, defined as JSON, executed by Meta.

  7. 07

    Click-to-WhatsApp Ads

    Integration with Meta Ads Manager so ad clicks land in a conversation you can answer.

  8. 08

    Cross-channel fallback

    Add fallback: "sms" to any send — session expiry routes through SMS automatically.

  9. 09

    Inbound message webhooks

    HMAC-signed events for inbound messages, read receipts, reactions, and template state.

  10. 10

    2B+ users on one endpoint

    Two billion-plus monthly WhatsApp users addressable from a single bird.whatsapp.send call.

Why we build WhatsApp

We were one of the first WhatsApp BSPs. We're still one of the few that ship code with you.

WhatsApp is gated. You need an approved template; you need an opted-in session window; you need a Meta business verification. That part doesn't change — and won't. What changes is whether your BSP makes those gates easier or harder to walk through — by exposing them in your code, on webhooks you can subscribe to, in errors that say exactly what's wrong. We chose the first.

order-shipped.ts
200 · 480ms
import { BirdClient } from "@bird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

const { data, error } = await bird.whatsapp.send({
  to:       "+15005550009",
  template: "order_shipped",
  locale:   "en_US",
  variables: {
    customer_name:   "Ada",
    order_id:        "BRD-49217",
    tracking_url:    "https://track.bird.dev/49217",
    eta:             "Thursday, May 21",
  },
}).safe();

if (error) throw error;
console.log(data.id);
// → "wa_msg_8nB91Yk3p..."

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": "whatsapp.read",
  "id":   "evt_7kQ02v...",
  "created_at": "2026-05-19T15:42:08.114Z",
  "data": {
    "wa_msg_id":   "wa_msg_8nB91Yk3p",
    "from":        "+15551234567",
    "to":          "+15005550009",
    "conversation_id": "wa_conv_3pX1g7t",
    "template":    "order_shipped",
    "delivered_at": "2026-05-19T15:42:01.802Z",
    "read_at":      "2026-05-19T15:42:08.020Z"
  }
}

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.

  • whatsapp.queuedAccepted by the API and queued for send to Meta.
  • whatsapp.sentHanded off to Meta's Cloud API.
  • whatsapp.deliveredMeta reports the message landed on the recipient's device.
  • whatsapp.readRecipient opened the message (if read receipts are on).
  • whatsapp.failedPermanent failure — reason code in the payload.
  • whatsapp.receivedInbound message from a user inside the 24h session window.
  • whatsapp.template.approvedMeta approved a template you submitted.
  • whatsapp.template.rejectedMeta rejected a template — rejection reason in the payload.

Fallback to SMS is one attribute, not a second integration.

If WhatsApp can't deliver — session expired, recipient never opted in, template not yet approved — Bird routes the same message over SMS in the same request. Same auth, same idempotency contract, same webhook shape on the other end.

WhatsApp with fallback.

whatsapp + fallback
await bird.whatsapp.send({
  to:       "+15005550009",
  template: "order_shipped",
  variables: { order_id: "BRD-49217" },
  fallback: "sms",
});

One payload, one auth. Session expiry, opt-in gap, unapproved template — all route through SMS automatically.

SMS direct.

sms
await bird.sms.send({
  from: "Bird",
  to:   "+15005550006",
  text: `Your order BRD-49217 has shipped.`,
});

The same wires, addressed directly. Use it when you want the SMS path explicitly.

From $0.005 per message + Meta's conversation fee at cost.

Priced by usage. We pass Meta's conversation fee through at cost — no markup. Volume discounts auto-apply above 100K/mo and again above 1M/mo. 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 MCP server — tools for every channel we expose, with scoped agent keys.

Cursor