3.0 KiB
MessageBird — @suaveplan/sms-providers
(no submodules)
Purpose
Real MessageBird SMS provider implementing SmsProvider from @suaveplan/sms. POSTs to /messages with Authorization: AccessKey <key>; 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
AccessKeyauth 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/nbfwindow enforcement and optionalpayload_hashcross-check. - Injectable
nowMs+toleranceMsso tests pin the clock and the production deployment can widen the freshness window if needed. parseInbounddiscriminates 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
import { MessageBirdProvider } from "@suaveplan/sms-providers";
const mb = new MessageBirdProvider({ accessKey: "test_…" });
await mb.send({ to: "+15551234567", from: "Suaveplan", body: "hi" });
Usage: Advanced
import { MessageBirdProvider } from "@suaveplan/sms-providers";
const mb = new MessageBirdProvider({ accessKey: "live_…" });
const ok = await mb.verifyWebhookSignature(
"<header>.<payload>.<sig>",
"shared-signing-key",
{ bodyHashHex: "<sha256-hex>", 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.