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

@absolutejs/dispatch-sinch

v0.3.0

Published

Production Sinch Conversation API adapter for AbsoluteJS with multichannel fallback, signed durable webhooks, consent, readiness, and 10DLC workflows.

Readme

@absolutejs/dispatch-sinch

Production Sinch Conversation API messaging for @absolutejs/dispatch.

Install

bun add @absolutejs/dispatch-sinch @sinch/sdk-core

This package uses real npm releases and has no install-time lifecycle hooks, local file dependencies, or overrides.

What it covers

  • SMS, MMS, RCS, WhatsApp, Viber Business, Messenger, Instagram, Telegram, KakaoTalk, LINE, and WeChat through the recommended Conversation API
  • Ordered channel_priority_order fallback with one generic message safely transcoded by Sinch
  • Text, one-media, omnichannel template, portable card/action, and guarded extensions.sinch content
  • Atomic provider/project/tenant-scoped idempotency and indeterminate-outcome handling through @absolutejs/reliability
  • HmacSHA256 verification over the exact raw callback body, nonce, and timestamp, with replay bounds and one-secret rotation
  • Fast durable webhook intake followed by an out-of-band recovery drain, stable provider-retry deduplication, delivery/inbound/choice event normalization, provider opt events, WhatsApp marketing preferences, and explicit SMS STOP/START/HELP parsing
  • Live app/channel/webhook readiness, asynchronous channel capability lookup, multi-project tenant routing, E.164 and WhatsApp business-scoped recipient identities, a concrete OAuth registration client, 10DLC brand/campaign/number workflows, and toll-free verification

The standalone Sinch SMS API is intentionally not used because Sinch marks it end-of-sale for new integrations.

Minimal sending

import { createDispatcher } from "@absolutejs/dispatch";
import { createSinchAdapter } from "@absolutejs/dispatch-sinch";
import { SinchClient } from "@sinch/sdk-core";

const client = new SinchClient({
  conversationRegion: "us",
  keyId: process.env.SINCH_KEY_ID!,
  keySecret: process.env.SINCH_KEY_SECRET!,
  projectId: process.env.SINCH_PROJECT_ID!,
});

const messaging = createSinchAdapter({
  appId: process.env.SINCH_APP_ID!,
  client,
  projectId: process.env.SINCH_PROJECT_ID!,
});

const dispatch = createDispatcher({ messaging });
await dispatch.messaging({
  content: { kind: "text", text: "Production latency is elevated." },
  fallbacks: [{ transport: "sms" }],
  idempotencyKey: "incident-42:recipient-7",
  to: { address: "+12025550100", transport: "rcs" },
});

Use a durable idempotency store for every retryable production send and a durable webhook inbox for callbacks. createSinchWebhookHandler requires a trusted route-to-account resolver so the correct secret is selected before the raw body is parsed. Configure that URL as a registered Conversation API webhook in Sinch; the adapter intentionally does not emit a per-message callback_url, because override callbacks use a separate signing-secret contract.

The HTTP handler authenticates and durably stores each callback, then returns 202 without waiting for application code. Run drainSinchWebhookInbox() in a worker with the same durable inbox, consent ledger, scope resolver, and event handler. Consent writes and application effects share the same retry path, so a temporary ledger failure cannot complete a STOP event prematurely.

Compliance boundary

createSinchRegistrationClient() uses short-lived OAuth credentials against Sinch's US Registration API and Numbers API. Pass it to createSinchRegistrationManager() to submit and inspect 10DLC brands and campaigns, qualify use cases, preserve the number's SMS service plan while linking an approved campaign, and submit toll-free verification evidence.

import {
  createSinchRegistrationClient,
  createSinchRegistrationManager,
} from "@absolutejs/dispatch-sinch";

const registrations = createSinchRegistrationManager(
  createSinchRegistrationClient({
    keyId: process.env.SINCH_KEY_ID!,
    keySecret: process.env.SINCH_KEY_SECRET!,
  }),
  process.env.SINCH_PROJECT_ID!,
);

These are operational workflows, not legal certification. Your application remains responsible for consent evidence, privacy/terms, quiet hours, opt-out testing, and carrier-specific program rules.

License

Apache-2.0