npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@messagebird/sdk

v0.7.2

Published

Official TypeScript SDK for the Bird API.

Readme

@messagebird/sdk

The official TypeScript SDK for the Bird API — fully typed, edge-ready, ESM.

📚 Documentation: https://bird.com/docs/sdks/typescript

Requirements

  • Node.js 20.3+ or a modern edge runtime (Cloudflare Workers, Vercel Edge, Deno). The SDK uses only web-standard APIs (fetch, AbortSignal, Web Crypto) and ships no Node built-ins.
  • ESM package. import works everywhere. require("@messagebird/sdk") also works on Node 20.19+ (via require(esm)); on older runtimes, load it with await import("@messagebird/sdk").

Install

pnpm add @messagebird/sdk

This SDK is generated from Bird's public OpenAPI bundle inside Bird's internal monorepo, which is the single source of truth; this repository tracks tagged releases. Generation runs in the monorepo, so pnpm generate won't work from a clone here — see CONTRIBUTING.md.

Quickstart

import { BirdClient } from "@messagebird/sdk";

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

const msg = await bird.email.send({
  from: { email: "[email protected]", name: "Bird" },
  to: ["[email protected]"],
  subject: "Hello from Bird",
  html: "<p>My first Bird email.</p>",
});

console.log(msg.id, msg.status);

The region is inferred from the API key prefix (bk_{region}_…). For a local or self-hosted server, pass baseUrl (which overrides region resolution).

Client defaults

Set channel defaults and the webhook secret once at construction. Defaulted fields become optional on each call (the per-call value wins), enforced by the types.

const bird = new BirdClient({
  apiKey: process.env.BIRD_API_KEY!,
  email: { from: "[email protected]" }, // now optional in email.send
  webhooks: { secret: process.env.BIRD_WEBHOOK_SECRET! },
});

await bird.email.send({ to: ["[email protected]"], subject: "Hi", html: "…" });

Email

await bird.email.send({ from, to, subject, html }); // resolves when accepted (202)
await bird.email.get(messageId); // aggregate delivery status

// `await` yields the first page; `for await` walks every message across pages.
for await (const message of bird.email.list()) {
  console.log(message.id);
}

WhatsApp

await bird.whatsapp.send({ to, template }); // resolves when accepted (202); Bird picks the sender from the template's category
await bird.whatsapp.get(messageId); // delivery status + failure detail

// `await` yields the first page; `for await` walks every message across pages.
for await (const message of bird.whatsapp.list()) {
  console.log(message.id);
}

const { data } = await bird.whatsapp.listEvents(messageId); // full lifecycle timeline, not paginated
const { data: templates } = await bird.whatsappTemplates.list(); // the workspace's Meta-approved templates

Webhooks

unwrap verifies a delivery's Standard Webhooks signature and returns a typed, discriminated event. Pass the raw request body — never the parsed JSON. Set the signing secret once via webhooks: { secret } on the client (or pass { secret } per call).

const event = bird.webhooks.unwrap(rawBody, request.headers);
switch (event.type) {
  case "email.delivered":
    console.log(event.email_id, event.recipient); // narrowed; fields are flat
    break;
  default: // unknown future events land here — forward-compatible
}

Endpoint management (registering/listing webhook endpoints) is not in this release; it returns once the delivery substrate stabilises.

Errors

Methods throw on failure with a typed error hierarchy you narrow with instanceof:

import { BirdRateLimitError, BirdValidationError, BirdAPIError } from "@messagebird/sdk";

try {
  await bird.email.send({
    from: { email: "[email protected]", name: "Bird" },
    to: ["[email protected]"],
    subject: "Hello from Bird",
    html: "<p>My first Bird email.</p>",
  });
} catch (err) {
  if (err instanceof BirdRateLimitError) console.log(`rate limited — retry in ${err.retryAfter}s`);
  else if (err instanceof BirdValidationError) console.error(err.details);
  else if (err instanceof BirdAPIError) console.error(err.code, err.requestId);
  else throw err;
}

Every API error carries statusCode, requestId, and type. The core retries safely on 429/5xx/network failures (mutations reuse one idempotency key across attempts).

Prefer to branch on a value instead of catching? Use .safe():

const { data, error } = await bird.email
  .send({
    from: { email: "[email protected]", name: "Bird" },
    to: ["[email protected]"],
    subject: "Hello from Bird",
    html: "<p>My first Bird email.</p>",
  })
  .safe();
if (error) console.error(error.message);
else console.log(data.id);

And .withResponse() exposes transport metadata (status, headers, request id) on success:

const { data, response } = await bird.email.list().withResponse();
response.headers.get("ratelimit-remaining");

Escape hatch

For endpoints the typed resources don't cover yet, request<T>() runs the full lifecycle (auth, retries, idempotency, error mapping) — you supply the response type:

const domains = await bird.request<DomainList>({ method: "GET", path: "/v1/email/domains" });

Configuration

new BirdClient({
  apiKey: "bk_eu1_…",
  region: "eu1", // override the key-prefix region
  baseUrl: "http://localhost:8080", // override entirely (local/self-hosted)
  timeout: 60_000, // per-attempt timeout (ms)
  maxRetries: 2,
  fetch: customFetch, // proxying, edge adapters, testing
  defaultHeaders: { "X-My-Header": "…" },
});