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

@crediball/sdk

v0.19.0

Published

TypeScript SDK for Crediball — usage-based credit billing for AI apps.

Readme

@crediball/sdk

TypeScript SDK for Crediball — credits-based monetization for AI apps. Wrap the actions your app performs; Crediball auto-discovers them and you price them in the dashboard. No pricing, prices, or manifests in code.

npm install @crediball/sdk

Fastest start — npx @crediball/sdk init

npx @crediball/sdk init

Detects your framework (Next.js / Vite / CRA), writes CREDIBALL_API_KEY (and, if you pass it, the publishable key with the correct public-env prefix) into the right env file without clobbering anything, and prints the two lines below plus the one thing only you can do: wrap your actions. The API base URL already defaults to the hosted API, so there's nothing else to configure. Pass --key cb_live_…, --publishable-key cb_pub_…, or --yes to run it non-interactively.

Quick start (server-side)

Wrap the business action your app performs — not the AI call underneath it:

import crediball from "@crediball/sdk";

crediball.init(process.env.CREDIBALL_API_KEY!, {
  baseUrl: process.env.CREDIBALL_API_URL, // defaults to the hosted API
});

// crediball.action() does four things in one call:
//   1. registers "summarize" if Crediball hasn't seen it (auto-discovery)
//   2. checks + deducts its credits BEFORE the work runs (live mode)
//   3. runs your callback and returns its result unchanged
//   4. lets the optional AI wrappers (below) enrich it with model/token telemetry
const summary = await crediball.action("summarize", "u123", () => summarizeDocument(pdf));

Because billing lives at the action boundary, you can switch OpenAI → Anthropic, add another model call, or rewrite the internals of the callback without ever touching the billing code. That separation is the whole point.

Every app starts in sandbox: every action is observed, nothing is billed. Activate the actions you want to charge for in the dashboard, set a credit cost, and flip the app to live — then action/track consume credits from the given user. Add a new action six months later and it simply appears in the dashboard, waiting for a price — no config, no sync, no manifest.

Registering a user at signup? Use identify

track/action already register a user the first time they do something, but if you'd rather have new users show up in the dashboard right at signup — including ones who never end up doing anything billable — call identify there:

await crediball.identify(user.id);

It's create-if-absent, so calling it again later (or letting track/action run before it) is a safe no-op.

Just recording an action? Use track

When there's no result to wrap (fire-and-forget, or you bill at a coarser boundary), call track directly — it's the same billing under the hood:

await crediball.track("generate_poem", "u123");

API

| Function | Description | |---|---| | crediball.init(apiKey, { baseUrl?, fetch? }) | Initialize the shared client once at startup (server-side). | | crediball.identify(userId, { initialCredits? }) | Register a user (e.g. at signup), create-if-absent. Grants the signup bonus, if configured. Optional — action/track register on first activity anyway. | | crediball.action(action, userId?, fn, { metadata? }) | The happy path. Register-if-new, deduct credits before fn runs, run fn, return its result. AI wrappers inside fn enrich instead of billing again. | | crediball.track(action, userId?, { metadata? }) | Record an action without wrapping a callback. Sandbox: observed. Live + activated + userId: bills its credits. | | crediball.getClient() | The shared client, for the purchase helpers below. |

The shared client also exposes purchase/paywall helpers:

| Method | Description | |---|---| | topup({ userId, packageId?, amount?, metadata? }) | Add credits. Pass packageId (from listPackages()) to auto-resolve credits + price. | | getBalance(userId) | Return the user's current balance. | | listPackages({ userId? }) | Top-up options: { currency, packages, subscriptionPlans, customTopup, signupBonus }. | | subscribe / cancelSubscription / getUserSubscription | Manage an end user's recurring subscription. |

Errors

  • InsufficientCreditsError — balance too low in live mode (catch it to show your paywall).
  • CrediballApiErrorany other non-2xx response, plus config/network failures (.status, .body, .message). Catch this too so a misconfigured baseUrl/key or an unreachable API surfaces as a clean message instead of an unhandled 500:
import { InsufficientCreditsError, CrediballApiError } from "@crediball/sdk";
try {
  await crediball.track("generate_poem", "u123");
} catch (e) {
  if (e instanceof InsufficientCreditsError) {/* show paywall / top-up UI */}
  else if (e instanceof CrediballApiError) {/* config/network error — surface cleanly */}
  else throw e;
}

Optional: auto-instrument your AI calls — @crediball/sdk/ai

The /ai subpath is an enrichment layer on top of your actions. It wraps your model(s)/client(s) once so every AI call underneath contributes provider, model, latency and token telemetry — across the Vercel AI SDK and the raw OpenAI / Anthropic / Google (Gemini) SDKs, plus a catch-all for anything else. It has no dependencies — your AI libraries are detected structurally.

Use it two ways:

  • Inside crediball.action(...) (recommended): the wrappers enrich the action with model/token telemetry and never bill a second timeaction already took the charge, up front. You get "which model/how many tokens did summarize use?" in the dashboard for free, and billing stays anchored to the business action.
  • Standalone (no action around them): the wrappers become the billing mechanism themselves — each wrapped call tracks its own event. Handy when the model call is the unit you price (per image, per transcription-minute), or as a low-touch way to cover a generic dispatcher without editing every call site.

Key actions by use-case, not by model. One model can back many actions (override the event per call); many models can back one action (share an event key). The model/provider/modality are recorded as metadata.

import crediball from "@crediball/sdk";
import { wrapOpenAI, wrapAnthropic, wrapGemini, crediballMiddleware, instrument, withUser }
  from "@crediball/sdk/ai";

crediball.init(process.env.CREDIBALL_API_KEY!);

// Raw clients — wrap once; text, image, audio & video calls are all tracked.
const openai = wrapOpenAI(new OpenAI(), { event: "assistant" });

// Vercel AI SDK — one middleware covers every text provider:
const model = wrapLanguageModel({ model: openai_("gpt-4o"), middleware: crediballMiddleware({ event: "chat" }) });
await generateText({ model, prompt, providerOptions: { crediball: { event: `reader_turn_${mode}`, userId } } });

// Anything else (custom provider, AI SDK image/speech) — the catch-all:
const makeCover = instrument((p: string) => openai.images.generate({ model: "gpt-image-1", prompt: p }),
  { event: "cover_art", modality: "image" });

// Thread the end user through a request so raw-client calls bill them, no signature changes:
await withUser(session.userId, () => handleRequest(req));

When a wrapper bills standalone, tracking fires before the model call, so in live mode an out-of-credits user is stopped with InsufficientCreditsError before the expensive request runs. embeddings/moderations are off by default (pass includeOptIn: true). A standalone wrapper bills per model call, so one user action that fans out into several calls bills several times — to bill once for the whole action, wrap it in crediball.action(...) (the gate then fires up front, before any model call, and the wrappers inside only enrich).

Token usage is captured automatically: after a non-streaming text call, the wrappers read the response's token counts and report them (a separate, non-billing call) so the dashboard shows tokens per action/model. No extra code — tokens never affect billing. For a custom provider, pass a tokens: (result) => ({ input, output, total }) extractor to instrument().

Principles

  • Bill the action, not the AI call. Wrap the business action with crediball.action(...); the AI wrappers are an optional telemetry layer on top.
  • No pricing in code. Crediball auto-discovers actions; set credit costs in the dashboard.
  • Server-side only. Never ship your cb_live_ key to the browser.
  • Pair with @crediball/react for drop-in, unbranded credit UI.