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

@iblusend/sdk

v0.2.2

Published

Official TypeScript SDK for the iBluSend iMessage API: send texts, media, voice memos and tapbacks, read conversations and groups, manage contacts and opt-out, verify webhooks, prepare FaceTime calls. Zero dependencies.

Readme

@iblusend/sdk

The official TypeScript client for the iBluSend iMessage API: send texts, media, voice memos and tapbacks from your own Macs, read conversations and groups, manage contacts and opt-out, verify webhooks, and prepare FaceTime Audio calls.

  • Typed requests and responses for every endpoint, pinned to the public OpenAPI contract by tests
  • Zero runtime dependencies — Node 18+, Bun, Deno, Cloudflare Workers, anywhere fetch exists
  • Webhook signature verification with a constant-time compare
  • Sensible retries, idempotency keys, per-request timeouts
  • ESM and CommonJS builds, bundled type definitions

Docs: https://iblusend.com/developers/docs/sdk · API reference: https://iblusend.com/developers/docs · Spec: https://iblusend.com/openapi.yaml

Install

npm install @iblusend/sdk

Quickstart

import { IBluSend } from "@iblusend/sdk";

const client = new IBluSend({ apiKey: process.env.IBLU_KEY! });

// Paced send (default) — queues through the drip pipeline
const sent = await client.messages.send({ to: "+13035550101", message: "Hey 👋" });

// Instant send, safe to retry thanks to the Idempotency-Key
await client.messages.send(
  { to: "+13035550101", message: "Your code is 4821", send_mode: "instant" },
  { idempotencyKey: "otp-4821-user-77" },
);

const status = await client.messages.status(sent.message_id);
const thread = await client.conversations.get({ phone: "+13035550101", limit: 50 });

Create a key under Developer → API Keys. An iblu_test_… key runs against the sandbox on every plan, including free — client.sandbox reads true.

What the client covers

| Resource | Methods | |---|---| | client.messages | send, sendVoiceMemo, status | | client.conversations | get, list, messages | | client.groups | list, get, send, create, rename, setPhoto, addMembers, removeMembers, leave, command | | client.lines | list | | client.signals | react, unreact, typing, markRead | | client.contacts | list, create, update | | client.optOut | get, set | | client.bot | get, set | | client.capability | check | | client.usage | get | | client.inbound | ingest | | client.calls | lines, prepare, get, listIncoming, end, transfer, settings, updateSettings, logs, log |

calls.settings and calls.updateSettings arrive in 0.2.1; earlier versions do not have them. calls.logs and calls.log arrive in 0.2.2.

Anything else: client.request(operationId, { path, query, body, options }) returns { data, response, idempotentReplay } for any operation in OPERATIONS.

Verify a webhook

// Next.js App Router
import { parseWebhook, readWebhookHeaders, WebhookSignatureError } from "@iblusend/sdk";

export async function POST(req: Request) {
  const raw = await req.text(); // the RAW body — never re-serialize parsed JSON
  try {
    const event = await parseWebhook(raw, readWebhookHeaders(req.headers), process.env.IBLU_WEBHOOK_SECRET!);
    // event.event, event.event_id (dedupe on it), event.data
    return new Response("ok");
  } catch (err) {
    if (err instanceof WebhookSignatureError) return new Response("bad signature", { status: 401 });
    throw err;
  }
}

verifyWebhookSignature(rawBody, signatureHeader, secret) returns a boolean if you only want the check.

Errors and retries

import { IBluSendError, IBluSendConnectionError } from "@iblusend/sdk";

try {
  await client.messages.send({ to: "+13035550101", message: "hi", send_mode: "instant" });
} catch (err) {
  if (err instanceof IBluSendError) {
    err.status;    // 409
    err.code;      // "no_online_device"
    err.rateLimit; // on a rate-limit 429: { retryAfter, resetAt, limit, remaining }
  } else if (err instanceof IBluSendConnectionError) {
    err.timedOut;  // true when the client-side timeout fired
  }
}

Reads, the idempotent DELETEs, and any POST carrying an idempotencyKey are retried up to twice (configurable) on a dropped connection, 408, 502, 503, 504, or a 429 whose Retry-After is ten seconds or less. A plain POST is never retried. A 429 asking for a longer wait is thrown at once with err.rateLimit filled in.

Instant sends are limited to 10 a minute per key. Daily limits count distinct cold recipients per line; a send past them fails with 429 device_daily_cap_exceeded and no Retry-After. Retrying the same new contact later that day will not help; replies to contacts who wrote back still go out.

Options

new IBluSend({
  apiKey,            // required
  baseUrl,           // default https://api.iblusend.com/functions/v1
  appBaseUrl,        // default https://iblusend.com (Calls API)
  fetch,             // bring your own
  timeoutMs: 30_000, // per request
  maxRetries: 2,     // retryable requests only
});

License

MIT