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

@fabric-messaging/sdk

v0.1.0-beta.9

Published

Official TypeScript SDK for the Fabric communications platform

Downloads

652

Readme

Fabric TypeScript SDK

The official server-side TypeScript client for sending and inspecting messages with Fabric.

Public prerelease: 0.1.0-beta.9. Every release moves the latest tag, so a plain install gets the newest build — the beta tag is frozen at an older prerelease and should not be used. The package is ESM-only by design — Node.js 22.12+ (the supported floor) can require() it natively, so there is no separate CommonJS build.

Install

pnpm add @fabric-messaging/sdk

Requires Node.js 22 or newer and a Fabric secret key. Create a sandbox key in Dashboard → Applications → API keys, then store it outside source control:

FABRIC_API_KEY=sk_test_...

Send your first SMS

import { Fabric } from "@fabric-messaging/sdk";

const fabric = new Fabric({ apiKey: process.env.FABRIC_API_KEY! });

const result = await fabric.sms.send(
  {
    to: "+233545227189",
    senderId: "SANDBOX",
    body: "Your first Fabric message",
  },
  { idempotencyKey: "quickstart-first-message" },
);

console.log(result.data.id, result.data.status, result.requestId);

Use a unique, stable idempotency key for the business action. Retrying the same action with the same key prevents a duplicate charge/message. View the returned message ID in Dashboard → Logs.

Retrieve and list messages

const message = await fabric.sms.retrieve("msg_...");

const page = await fabric.sms.list({ limit: 50 });
console.log(page.data.items.length, page.data.nextCursor);

// Or walk the whole log — the iterator follows next_cursor until it is null.
for await (const summary of fabric.sms.iterate({ limit: 100 })) {
  console.log(summary.id, summary.status);
}

Message, email, and webhook-delivery lists are cursor-paginated (limit 1–100, default 50). Treat nextCursor as opaque: pass it back exactly as returned. email.iterate, messages.iterateDeliveries, and webhooks.iterateDeliveries follow the same pattern.

Send a verification code

const started = await fabric.verify.start({ to: "+233545227189" });
const checked = await fabric.verify.check({ id: started.data.id, code: "123456" });

Fabric generates the code and sends its own wording. To send your own instead, pass template — the stable key of a released SMS message definition — plus any variables it declares:

await fabric.verify.start({
  to: "+233545227189",
  template: "merchant.otp",
  variables: { merchant_name: "Jasper's Market" },
  locale: "fr-FR",
});

Chosen per call, so one integration can send differently-branded codes for each merchant it serves. A few constraints are worth knowing before you author one:

  • The key must belong to an application, because the key is what names the environment the definition was released in. A definition released into a different application's environment answers verify_template_not_released.
  • code, expires_minutes and expires_seconds are ours. Your template renders them, but passing one as a variable is a 400 — the code is generated server-side and never accepted from a caller. Variable names reach the API verbatim, so they are the names the template declares.
  • The definition must be transactional and its body must contain {{code}}. Both are checked when the code is rendered, before any money moves, so an ineligible template costs nothing.

Send a sandbox Email

const email = await fabric.email.send(
  {
    to: "[email protected]",
    from: "[email protected]",
    subject: "Welcome",
    text: "Your Fabric sandbox Email works.",
  },
  { idempotencyKey: "welcome-email-1" },
);

Sandbox Email is simulated inside Fabric and never contacts an external provider. Live keys fail closed until an approved sending domain and production Email provider are configured.

Verify webhooks

Always pass the untouched raw request body—not parsed/re-serialized JSON:

const event = fabric.webhooks.verify({
  payload: rawBody,
  signature: request.headers["fabric-signature"],
  secret: process.env.FABRIC_WEBHOOK_SECRET!,
});

if (event.type === "message.delivered") {
  console.log(event.data);
}

if (event.type === "unknown") {
  console.log("Upgrade the SDK to handle", event.originalType);
}

Verification uses HMAC-SHA256, constant-time comparison, and a five-minute timestamp tolerance by default. Invalid, malformed, or stale events throw WebhookVerificationError. Known direct-message events are message.accepted, message.sent, message.delivered, message.undelivered, message.failed, and message.inbound; a correctly signed newer event returns the explicit unknown variant.

Inspect and replay a dead endpoint-specific delivery without changing its event ID:

const dead = await fabric.webhooks.listDeliveries(endpointId, { state: "dead" });
const first = dead.data.items[0];
if (first) {
  await fabric.webhooks.replayDelivery(endpointId, first.id);
}

Webhook delivery is at least once. Persist event IDs under a unique constraint before applying side effects; timeout-after-accept and manual replay can legitimately deliver the same event again. The verified event always contains id and createdAt; missing envelope identity is rejected even when the signature itself is valid.

Handle errors

import { AuthenticationError, FabricError, RateLimitError } from "@fabric-messaging/sdk";

try {
  await fabric.sms.list();
} catch (error) {
  if (error instanceof RateLimitError) {
    console.error("Retry later", error.retryAfter, error.requestId);
  } else if (error instanceof AuthenticationError) {
    console.error("Rotate or replace the API key", error.requestId);
  } else if (error instanceof FabricError) {
    console.error(error.code, error.message, error.requestId);
  }
}

Errors never include the API key, authorization header, or message body. Optional logger callbacks receive only method/path/status/retry/request metadata.

Sandbox and live environments

sk_test_... keys set fabric.environment to sandbox; sk_live_... keys set it to live. No separate environment setting can conflict with the key. Moving to live delivery changes only FABRIC_API_KEY, but requires an approved sender ID, billing, provider configuration, and applicable Ghana/Nigeria compliance approval.

Sandbox sends appear on the workspace’s two-way Virtual Phone and never contact a carrier. The sandbox guide on the Fabric docs site (/docs/get-started/sandbox-and-keys) covers the stable virtual number, STOP/START replies, and deterministic test recipients.

This package is for trusted server runtimes only. Never import it into browser code or expose secret keys in client bundles, logs, commits, screenshots, or support tickets.

Supported resources

  • fabric.messages.send, preview, retrieveDelivery, listDeliveries, iterateDeliveries, listDeliveryWebhooks (managed, template-key messages)
  • fabric.sms.send, retrieve, list, iterate
  • fabric.sms.sendBatch, retrieveBatch
  • fabric.email.send, retrieve, list, iterate
  • fabric.whatsapp.send, retrieve, list, iterate
  • fabric.senderIds.create, list (bounded — sender IDs are few; not paginated)
  • fabric.verify.start, check
  • fabric.wallet.retrieve
  • fabric.webhooks.create, list, remove/disable, listDeliveries, iterateDeliveries, replayDelivery, verify

webhooks.remove and webhooks.disable are the same call: the API soft-deletes, marking the endpoint disabled while retaining its delivery history.

See the Fabric docs site (/docs/sdks-tools/node) and the bundled OpenAPI reference for retries, security, framework patterns, versioning, and the public wire contract. Report SDK issues through the repository issue tracker and include the request ID—but never credentials or message content.

Maintainers validate a release candidate with pnpm --filter @fabric-messaging/sdk release:check; this builds, tests, inspects, installs, and imports the packed artifact from a clean temporary project.