# MessageBird — `@suaveplan/sms-providers` _(no submodules)_ ## Purpose Real MessageBird SMS provider implementing `SmsProvider` from `@suaveplan/sms`. POSTs to `/messages` with `Authorization: AccessKey `; status fetched via `GET /messages/{id}`. Inbound webhook signature verification follows the MessageBird Signed Webhooks v2 (`Messagebird-Signature-Jwt`) spec — a JWT HS256 carrying `iat`/`exp`/`nbf`/`payload_hash` claims; the verifier checks the timestamp window (default ±5 minutes), re-MACs the canonical `header.payload`, and constant-time compares the base64url-decoded signature. The class holds no in-flight state and routes every HTTP call through the injectable `FetchLike` seam. Tests stand up a `node:http` server on a random port and inject a `fetch` adapter that points at it. ## Features - `AccessKey` auth header per MessageBird's documented scheme. - JSON body with `recipients[]`, `originator`, `body`. - Status mapping covers `scheduled` / `sent` / `buffered` / `delivered` / `expired` / `delivery_failed`. - JWT HS256 webhook verifier with `iat` / `exp` / `nbf` window enforcement and optional `payload_hash` cross-check. - Injectable `nowMs` + `toleranceMs` so tests pin the clock and the production deployment can widen the freshness window if needed. - `parseInbound` discriminates between inbound messages and DLRs, recognising the standard CTIA opt-out keywords. - OTel — `send_total` + `send_duration_ms` + `signature_failures_total` + `webhook_verify_duration_ms`. ## Usage: Basic ```ts import { MessageBirdProvider } from "@suaveplan/sms-providers"; const mb = new MessageBirdProvider({ accessKey: "test_…" }); await mb.send({ to: "+15551234567", from: "Suaveplan", body: "hi" }); ``` ## Usage: Advanced ```ts import { MessageBirdProvider } from "@suaveplan/sms-providers"; const mb = new MessageBirdProvider({ accessKey: "live_…" }); const ok = await mb.verifyWebhookSignature( "
..", "shared-signing-key", { bodyHashHex: "", nowMs: Date.now(), toleranceMs: 60_000 } ); ``` ## API Reference | Symbol | Kind | Notes | |---|---|---| | `MessageBirdProvider` | class | Implements `SmsProvider`. | | `send(message, options?)` | method | `POST /messages`, returns `SmsDeliveryReport`. | | `getStatus(id)` | method | `GET /messages/{id}`. | | `mapStatus(raw)` | method | Canonical mapping. | | `verifyWebhookSignature(token, signingKey, options?)` | method | JWT HS256 verifier; throws `SIGNATURE_INVALID` on failure. | | `parseInbound(body)` | method | Discriminates into `InboundSmsEvent`. | ## Implementation Notes The verifier handles both standard Base-64 and base64url (`-`/`_` → `+`/`/`) inputs because MessageBird's JWT uses the URL-safe variant. `payload_hash` is checked only when both the JWT carries it and the caller supplies a `bodyHashHex`; missing on either side is treated as "skip" so callers can disable the body binding when their proxy strips bodies.