TypeScript SDK
@messagebird/sdk is the official TypeScript SDK for the Bird API — fully typed, ESM-only, and edge-ready. It runs on Node.js 20.3+ and modern edge runtimes (Cloudflare Workers, Vercel Edge, Deno) using only web-standard APIs (fetch, AbortSignal, Web Crypto). This page covers the client itself; the per-channel surfaces are documented on their own pages, starting with email.
Install
Esempio di codice
npm install @messagebird/sdk
# pnpm add @messagebird/sdk
# yarn add @messagebird/sdk
# bun add @messagebird/sdkConstruct a client
Esempio di codice
const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY!,
region: "eu1", // optional — override the region from the key prefix
baseUrl: "http://localhost:8080", // optional — overrides region entirely (local/self-hosted)
timeout: 60_000, // per-attempt timeout in ms (default 60_000)
maxRetries: 2, // retry budget for transient failures (default 2)
});Only apiKey is required. The region is inferred from the key's bk_{region}_ prefix (a bk_eu1_… key routes to https://eu1.platform.bird.com), so most clients are constructed with the key alone — see region inference for the resolution rules. You can also set channel defaults at construction (for example email: { from: "hello@acme.com" } makes from optional on every send) and the webhook signing secret via webhooks: { secret }.
First call
Esempio di codice
const msg = await bird.email.send({
from: { email: "onboarding@messagebird.dev", name: "Bird" },
to: ["delivered@messagebird.dev"],
subject: "Hello from Bird",
html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"await resolves to the API result directly — here an email message with its em_* id. For a runnable end-to-end walkthrough, follow the TypeScript quickstart.
Two-layer design
The SDK is a generated layer plus a hand-owned one. Wire types and the low-level HTTP plumbing are generated from Bird's OpenAPI spec, so request and response shapes are always contract-accurate; the surface you actually call — bird.email.send(...), the retry loop, idempotency, pagination, errors — is hand-written for ergonomics on top. Wire fields pass through verbatim in snake_case (category, created_at); only SDK-defined identifiers (method names, option keys like idempotencyKey) are camelCase. The same architecture is shared by the Go and Python SDKs — see SDK concepts.
Automatic idempotency and retries
Every mutation (POST, PATCH, DELETE) gets an auto-generated Idempotency-Key header, and that one key is reused across every retry attempt — so a retried send can never deliver twice. Pass { idempotencyKey: "order-1234" } in the per-call options to control the key yourself.
Retries are on by default (maxRetries: 2). The client retries network failures, per-attempt timeouts, and transient statuses (408, 429, 500, 502, 503, 504) with jittered exponential backoff, honoring the server's Retry-After header when present. Deterministic failures (4xx like 401, 404, 422) are never retried. Set maxRetries: 0 to disable, or override per call. The full lifecycle is described in SDK concepts.
Errors
Methods throw on failure with a typed hierarchy you narrow with instanceof. BirdError is the root; BirdAPIError covers every error response from the server, with one subclass per error type — including BirdAuthError (401), BirdRateLimitError (429, with retryAfter), BirdValidationError (422, with per-field details), and BirdPayloadTooLargeError (413). Transport failures with no HTTP response are siblings of BirdAPIError: BirdConnectionError and BirdTimeoutError.
Esempio di codice
import { BirdRateLimitError, BirdValidationError, BirdAPIError } from "@messagebird/sdk";
try {
await bird.email.send({
from: { email: "onboarding@messagebird.dev", name: "Bird" },
to: ["delivered@messagebird.dev"],
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 BirdAPIError carries statusCode, type, code (the stable E##### error code), requestId, and docUrl. Branch on the class (or the coarse type) for control flow; use code when you need to match one specific failure. Prefer branching on a value instead of catching? Every call also has .safe():
Esempio di codice
const { data, error } = await bird.email
.send({
from: { email: "onboarding@messagebird.dev", name: "Bird" },
to: ["delivered@messagebird.dev"],
subject: "Hello from Bird",
html: "<p>My first Bird email.</p>",
})
.safe();
if (error) console.error(error.message);
else console.log(data.id);Webhooks
bird.webhooks.unwrap(rawBody, headers) verifies an inbound delivery's Standard Webhooks signature and returns a typed, discriminated event. Always pass the raw request body — the signature is computed over the raw bytes, so parsing and re-serializing first is the classic webhook bug. A bad signature, stale timestamp, or malformed headers throws BirdWebhookVerificationError. See webhook verification for the cross-SDK contract and Webhooks for the platform side.
Next steps
- Email surface — send, get, list, channel defaults, and the response shapes.
- SDK concepts — idempotency, retries, pagination, regions, and webhooks across all Bird SDKs.
- API reference — the underlying HTTP API; bird.request<T>() reaches any endpoint the typed surface doesn't cover yet, with the same auth, retries, and idempotency.