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

@billing-io/sdk

v2.0.0

Published

Official billing.io JavaScript/TypeScript SDK -- non-custodial crypto checkout API

Readme

@billing-io/sdk

Official JavaScript/TypeScript SDK for the billing.io non-custodial crypto checkout API.

  • Zero runtime dependencies -- uses the built-in fetch API (Node 18+, Deno, Cloudflare Workers, browsers)
  • Full TypeScript type safety derived from the OpenAPI v2 specification
  • Automatic cursor-based pagination via async iterators
  • Webhook signature verification using the Web Crypto API

Installation

npm install @billing-io/sdk
yarn add @billing-io/sdk
pnpm add @billing-io/sdk

Quick start

Create a checkout and poll for status

import { BillingIO } from "@billing-io/sdk";

const billing = new BillingIO({ apiKey: "sk_live_..." });

// 1. Create a checkout
const checkout = await billing.checkouts.create({
  amount_usd: 49.99,
  chain: "tron",
  token: "USDT",
  metadata: { order_id: "ord_12345" },
});

console.log("Deposit to:", checkout.deposit_address);
console.log("Checkout ID:", checkout.checkout_id);

// 2. Poll for status
let status = await billing.checkouts.getStatus(checkout.checkout_id);

while (status.status !== "confirmed" && status.status !== "expired") {
  await new Promise((r) => setTimeout(r, status.polling_interval_ms));
  status = await billing.checkouts.getStatus(checkout.checkout_id);
  console.log(
    `Status: ${status.status} (${status.confirmations}/${status.required_confirmations})`,
  );
}

if (status.status === "confirmed") {
  console.log("Payment confirmed!", status.tx_hash);
}

Webhook verification

import { verifyWebhookSignature } from "@billing-io/sdk";

// In your webhook handler (e.g. Express, Next.js Route Handler, etc.)
export async function POST(req: Request) {
  const body = await req.text();
  const signature = req.headers.get("x-billing-signature")!;

  try {
    const event = await verifyWebhookSignature(
      body,
      signature,
      process.env.WEBHOOK_SECRET!, // whsec_...
    );

    switch (event.type) {
      case "checkout.completed":
        console.log("Payment completed:", event.data.checkout_id);
        // fulfill the order ...
        break;
      case "checkout.expired":
        console.log("Checkout expired:", event.data.checkout_id);
        break;
    }

    return new Response("ok", { status: 200 });
  } catch (err) {
    console.error("Webhook verification failed:", err);
    return new Response("Invalid signature", { status: 400 });
  }
}

You can also adjust the timestamp tolerance (default is 300 seconds / 5 minutes):

const event = await verifyWebhookSignature(body, signature, secret, {
  tolerance: 600, // 10 minutes
});

Error handling

import { BillingIO, BillingIOError } from "@billing-io/sdk";

const billing = new BillingIO({ apiKey: "sk_live_..." });

try {
  await billing.checkouts.create({
    amount_usd: -1, // invalid
    chain: "tron",
    token: "USDT",
  });
} catch (err) {
  if (err instanceof BillingIOError) {
    console.error("API error:", {
      type: err.type, // "invalid_request"
      code: err.code, // e.g. "invalid_amount"
      message: err.message, // human-readable description
      statusCode: err.statusCode, // 400
      param: err.param, // "amount_usd"
    });

    // Specific error types
    switch (err.type) {
      case "authentication_error":
        // bad API key
        break;
      case "rate_limited":
        // back off and retry
        break;
      case "idempotency_conflict":
        // idempotency key was reused with different params
        break;
      case "not_found":
        // resource does not exist
        break;
    }
  }
}

Pagination

Manual pagination

let page = await billing.checkouts.list({ limit: 10 });

for (const checkout of page.data) {
  console.log(checkout.checkout_id, checkout.status);
}

// Fetch the next page
if (page.has_more && page.next_cursor) {
  page = await billing.checkouts.list({
    limit: 10,
    cursor: page.next_cursor,
  });
}

Auto-pagination

Use the autoPaginate helper to iterate across all pages automatically:

for await (const checkout of billing.checkouts.list.autoPaginate({
  status: "confirmed",
})) {
  console.log(checkout.checkout_id, checkout.amount_usd);
}

This works for all list endpoints:

// All events for a specific checkout
for await (const event of billing.events.list.autoPaginate({
  checkout_id: "co_abc123",
})) {
  console.log(event.type, event.created_at);
}

// All webhook endpoints
for await (const endpoint of billing.webhooks.list.autoPaginate()) {
  console.log(endpoint.webhook_id, endpoint.url);
}

// All active customers
for await (const customer of billing.customers.list.autoPaginate({
  status: "active",
})) {
  console.log(customer.customer_id, customer.email);
}

// All subscriptions for a customer
for await (const sub of billing.subscriptions.list.autoPaginate({
  customer_id: "cus_abc123",
})) {
  console.log(sub.subscription_id, sub.status);
}

Customers

// Create a customer
const customer = await billing.customers.create({
  email: "[email protected]",
  name: "Alice",
  metadata: { tier: "enterprise" },
});

// List customers
const customers = await billing.customers.list({ status: "active" });

// Get a customer
const cust = await billing.customers.get("cus_abc123");

// Update a customer
await billing.customers.update("cus_abc123", { name: "Alice Smith" });

Payment Methods

// Create a payment method
const pm = await billing.paymentMethods.create({
  customer_id: "cus_abc123",
  type: "wallet",
  chain: "tron",
  address: "T...",
  label: "Main Wallet",
});

// List payment methods for a customer
const methods = await billing.paymentMethods.list({ customer_id: "cus_abc123" });

// Set as default
await billing.paymentMethods.setDefault("pm_abc123");

// Delete
await billing.paymentMethods.delete("pm_abc123");

Payment Links

// Create a payment link
const link = await billing.paymentLinks.create({
  amount_usd: 99.99,
  chain: "tron",
  token: "USDT",
});
console.log("Share this link:", link.url);

// List payment links
const links = await billing.paymentLinks.list({ status: "active" });

Subscriptions

// Create a plan
const plan = await billing.subscriptionPlans.create({
  name: "Pro Monthly",
  amount_usd: 29.99,
  interval: "monthly",
  token: "USDT",
  chain: "tron",
});

// Create a subscription
const sub = await billing.subscriptions.create({
  customer_id: "cus_abc123",
  plan_id: plan.plan_id,
  payment_method_id: "pm_abc123",
});

// Cancel a subscription
await billing.subscriptions.update(sub.subscription_id, { status: "cancelled" });

// List renewals
const renewals = await billing.subscriptionRenewals.list({
  subscription_id: sub.subscription_id,
});

// Retry a failed renewal
await billing.subscriptionRenewals.retry("ren_abc123");

Entitlements

// Create an entitlement
await billing.entitlements.create({
  subscription_id: "sub_abc123",
  feature_key: "api_calls",
  value: "10000",
});

// Check if a customer is entitled to a feature
const check = await billing.entitlements.check({
  customer_id: "cus_abc123",
  feature_key: "api_calls",
});

if (check.entitled) {
  console.log("Allowed:", check.value);
}

// Delete an entitlement
await billing.entitlements.delete("ent_abc123");

Payouts

// Create a payout intent
const payout = await billing.payoutIntents.create({
  amount_usd: 500.0,
  chain: "arbitrum",
  token: "USDC",
  destination_address: "0x...",
});

// Execute the payout
await billing.payoutIntents.execute(payout.payout_id);

// List settlements
const settlements = await billing.settlements.list({
  payout_id: payout.payout_id,
});

Revenue

// List revenue events
const events = await billing.revenueEvents.list({ type: "payment_received" });

// Get accounting summary
const accounting = await billing.revenueEvents.accounting({
  start_date: "2025-01-01T00:00:00Z",
  end_date: "2025-12-31T23:59:59Z",
});
console.log("Net revenue:", accounting.net_revenue_usd);

// Create an adjustment
await billing.adjustments.create({
  amount_usd: 10.0,
  type: "credit",
  description: "Goodwill credit",
  customer_id: "cus_abc123",
});

// List adjustments
const adjustments = await billing.adjustments.list({ type: "credit" });

Managing webhook endpoints

// Create
const endpoint = await billing.webhooks.create({
  url: "https://example.com/webhooks/billing",
  events: ["checkout.completed", "checkout.expired"],
  description: "Production webhook",
});
console.log("Secret (store this!):", endpoint.secret);

// List
const endpoints = await billing.webhooks.list();

// Get
const ep = await billing.webhooks.get("we_abc123");

// Delete
await billing.webhooks.delete("we_abc123");

Idempotent requests

Pass an idempotencyKey to safely retry checkout creation:

import { randomUUID } from "node:crypto";

const checkout = await billing.checkouts.create(
  {
    amount_usd: 49.99,
    chain: "tron",
    token: "USDT",
  },
  { idempotencyKey: randomUUID() },
);

If a request with the same key was already processed, the original response is returned. Keys expire after 24 hours.

Health check

const health = await billing.health.get();
console.log(health.status); // "healthy"
console.log(health.version); // "1.0.0"

Configuration

const billing = new BillingIO({
  // Required -- your secret API key
  apiKey: "sk_live_...",

  // Optional -- override the base URL (useful for local development)
  baseUrl: "http://localhost:8080/v1",
});

TypeScript

The SDK is written in TypeScript and ships with full type declarations. All request parameters, response objects, and error types are fully typed.

import type {
  Checkout,
  CheckoutStatus,
  CreateCheckoutRequest,
  Customer,
  Subscription,
  SubscriptionPlan,
  PayoutIntent,
  EventType,
  Chain,
  Token,
} from "@billing-io/sdk";

const params: CreateCheckoutRequest = {
  amount_usd: 100,
  chain: "arbitrum",
  token: "USDC",
};

Requirements

  • Node.js 18+ (or any runtime with a global fetch and crypto.subtle)
  • No runtime dependencies

License

MIT