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

@credit-engine/sdk

v1.0.0

Published

Credit Engine SDK — AI credits for SaaS in 5 minutes

Downloads

24

Readme

@credit-engine/sdk

AI credits for SaaS in 5 minutes. Add usage-based billing to your AI product without building a credit system from scratch.

Install

npm install @credit-engine/sdk

Quick Start

import { CreditEngine } from '@credit-engine/sdk';

const ce = new CreditEngine({
  apiKey: 'ce_live_xxx', // or ce_test_xxx for sandbox
});

// Check balance
const { balance } = await ce.getBalance('cus_xxx');

// Consume credits (optimistic, async in persistent mode)
const { balance: remaining } = await ce.consume('cus_xxx', 5, 'AI: chat completion');

// Consume or throw if insufficient
await ce.consumeOrFail('cus_xxx', 10, 'AI: image generation');

// Clean up on shutdown
await ce.destroy();

Configuration

const ce = new CreditEngine({
  apiKey: 'ce_live_xxx',          // Required. ce_live_ for production, ce_test_ for sandbox
  baseUrl: 'https://...',         // Custom API URL. Default: https://api.creditengine.dev
  mode: 'auto',                   // 'persistent' | 'stateless' | 'auto'. Default: 'auto'
  syncIntervalMs: 30000,          // Cache sync interval (persistent mode). Default: 30s
  gracefulDegradation: true,      // Allow ops when API is down. Default: true
  timeoutMs: 10000,               // Request timeout. Default: 10s
  maxRetries: 2,                  // Retry failed requests. Default: 2
  onError: (err) => log(err),     // Non-critical error callback
});

Modes

The SDK has two operating modes, auto-detected by default:

Persistent (servers, Docker, Railway)

Maintains an in-memory cache for sub-millisecond balance checks:

  • getBalance() returns from cache (<1ms)
  • consume() deducts locally and queues the API call (non-blocking)
  • Background sync every 30s corrects any drift
  • If the API goes down, operations continue against the local cache

Stateless (Vercel, Lambda, Cloudflare Workers)

Every call goes directly to the API:

  • No cache, no queue, no background processes
  • ~50-100ms per call (one HTTP round-trip)
  • Always consistent with the server
  • Idempotency keys still work (server-side dedup)

Auto-detection: if VERCEL, AWS_LAMBDA_FUNCTION_NAME, NETLIFY, or CLOUDFLARE_WORKER env vars exist, stateless is used. Otherwise, persistent.

// Force a specific mode
const ce = new CreditEngine({ apiKey: 'ce_live_xxx', mode: 'stateless' });

API Reference

getBalance(customerId, options?)

const { balance, customer_id, credit_name, breakdown } = await ce.getBalance('cus_xxx', {
  includeBreakdown: true, // Include per-product breakdown
});

consume(customerId, amount, description?, options?)

Deduct credits from a customer.

const { balance, transaction_id } = await ce.consume('cus_xxx', 5, 'AI: chat', {
  idempotencyKey: 'req_abc123',   // Prevent double-charging
  metadata: { model: 'gpt-4' },  // Attached to the transaction
});

consumeOrFail(customerId, amount, description?, options?)

Same as consume(), but throws InsufficientCreditsError if the customer doesn't have enough credits.

try {
  await ce.consumeOrFail('cus_xxx', 100, 'AI: batch job');
} catch (err) {
  if (err instanceof InsufficientCreditsError) {
    console.log(`Need ${err.requested}, have ${err.currentBalance}`);
  }
}

add(customerId, amount, options?)

Add credits to a customer (topup, refund, adjustment).

const { balance, transaction_id } = await ce.add('cus_xxx', 500, {
  type: 'topup',        // 'topup' | 'adjustment' | 'refund'
  description: 'Monthly credit grant',
  metadata: { source: 'subscription' },
});

getTransactions(customerId, options?)

Fetch paginated transaction history.

const { data, pagination } = await ce.getTransactions('cus_xxx', {
  limit: 20,
  offset: 0,
  type: 'consumption',  // Filter by type
});

createTopUpSession(options)

Create a Stripe Checkout session for self-service credit purchases.

const { checkoutUrl, sessionId } = await ce.createTopUpSession({
  customerId: 'cus_xxx',
  successUrl: 'https://app.example.com/credits?success=true',
  cancelUrl: 'https://app.example.com/credits',
});

// Redirect user to checkoutUrl

getUsageAnalytics(options?)

Get usage data as a time series.

const { data } = await ce.getUsageAnalytics({
  period: 'last_30_days',   // 'last_7_days' | 'last_30_days' | 'last_90_days' | 'current_month'
  groupBy: 'day',           // 'day' | 'week' | 'action'
  customerId: 'cus_xxx',    // Optional: filter by customer
});
// data: [{ day, consumed, added, net, transaction_count }]

getTopConsumers(options?)

const { data } = await ce.getTopConsumers({ period: 'last_30_days', limit: 10 });
// data: [{ customer_id, total_consumed, total_added, transaction_count }]

getActionBreakdown(options?)

const { data } = await ce.getActionBreakdown({ period: 'last_30_days' });
// data: [{ action, type, consumed, added, transaction_count }]

getBurnRate(options?)

const { data } = await ce.getBurnRate({ days: 30 });
// data: { daily_avg_consumed, daily_avg_added, net_daily_burn, projection_days_remaining }

getAnalyticsSummary(options?)

const { data } = await ce.getAnalyticsSummary({ period: 'last_30_days' });
// data: { total_consumed, total_added, net_change, total_transactions, active_customers, comparison: { ... } }

destroy()

Flush pending operations and stop background processes.

await ce.destroy();

pendingOperations

Number of queued deductions (persistent mode only).

console.log(ce.pendingOperations); // 0

Idempotency

Prevent double-charging with idempotency keys. If the same key is sent twice, the server returns the original transaction instead of creating a new one.

const key = `user_${userId}_action_${actionId}`;

// Safe to retry — will only charge once
await ce.consume('cus_xxx', 5, 'AI: chat', { idempotencyKey: key });
await ce.consume('cus_xxx', 5, 'AI: chat', { idempotencyKey: key }); // No-op, returns same tx

Error Handling

import {
  CreditEngineError,
  InsufficientCreditsError,
  RateLimitError,
  AuthenticationError,
} from '@credit-engine/sdk';

try {
  await ce.consumeOrFail('cus_xxx', 100, 'expensive op');
} catch (err) {
  if (err instanceof InsufficientCreditsError) {
    // err.currentBalance, err.requested
  } else if (err instanceof RateLimitError) {
    // err.retryAfter (seconds)
  } else if (err instanceof AuthenticationError) {
    // Invalid API key
  } else if (err instanceof CreditEngineError) {
    // err.code, err.status, err.details
  }
}

Sandbox Mode

Use ce_test_ keys for development and testing. Sandbox data is fully isolated from production.

const ce = new CreditEngine({ apiKey: 'ce_test_xxx' });
// All operations affect sandbox data only

TypeScript

Full type support with all response types exported:

import type {
  CreditEngineConfig,
  BalanceResponse,
  ConsumeResponse,
  AddResponse,
  Transaction,
  TransactionsResponse,
  TopUpSessionResponse,
  UsageAnalyticsResponse,
  AnalyticsPeriod,
} from '@credit-engine/sdk';

License

MIT