billSDK

Configuration

All configuration options for BillSDK

Options

const billing = billsdk({
  database: drizzleAdapter(db, { schema, provider: "pg" }),
  payment: stripePayment({ ... }),
  basePath: "/api/billing",
  secret: process.env.BILLSDK_SECRET,
  features: [...],
  plans: [...],
  plugins: [...],
  hooks: { before, after },
  logger: { level: "info", disabled: false },
});
OptionTypeDefaultDescription
databaseDBAdaptermemoryAdapter()Database adapter
paymentPaymentAdapter-Payment provider adapter
basePathstring/api/billingAPI base path
secretstring-Signing secret (required in production)
featuresFeatureConfig[][]Feature definitions
plansPlanConfig[][]Plan definitions
pluginsPlugin[][]Plugins
hooksobject-Request hooks
loggerobject-Logger configuration

Features

Features are capabilities you can gate per plan. Currently only boolean (on/off) features are supported.

features: [
  { code: "export", name: "Export Data" },
  { code: "api_access", name: "API Access" },
  { code: "priority_support", name: "Priority Support" },
]
PropertyTypeRequiredDescription
codestringYesUnique identifier
namestringYesDisplay name
type"boolean" | "metered" | "seats"NoFeature type (default: "boolean")

Feature codes are type-safe. When you call checkFeature, TypeScript only accepts codes you defined:

// Type error: "invalid_feature" is not a valid feature code
await billing.api.checkFeature({ customerId, feature: "invalid_feature" });

Plans

Plans define your pricing tiers. They exist only in code, not in the database.

plans: [
  {
    code: "free",
    name: "Free",
    description: "Get started",
    isPublic: true,
    prices: [{ amount: 0, interval: "monthly" }],
    features: ["export"],
  },
  {
    code: "pro",
    name: "Pro",
    prices: [
      { amount: 2000, interval: "monthly", currency: "usd" },
      { amount: 20000, interval: "yearly", trialDays: 14 },
    ],
    features: ["export", "api_access"],
  },
  {
    code: "enterprise",
    name: "Enterprise",
    isPublic: false, // Hidden from listPlans()
    prices: [{ amount: 9900, interval: "monthly" }],
    features: ["export", "api_access", "priority_support"],
  },
]

Plan Properties

PropertyTypeRequiredDescription
codestringYesUnique identifier
namestringYesDisplay name
descriptionstringNoPlan description
isPublicbooleanNoShow in listPlans() (default: true)
pricesPlanPriceConfig[]YesPricing options
featuresstring[]NoEnabled feature codes

Price Properties

PropertyTypeRequiredDescription
amountnumberYesPrice in cents (2000 = $20.00)
interval"monthly" | "quarterly" | "yearly"YesBilling cycle
currencystringNoISO 4217 code (default: "usd")
trialDaysnumberNoTrial period length

Database Adapters

Drizzle

import { drizzleAdapter } from "@billsdk/drizzle-adapter";

database: drizzleAdapter(db, {
  schema,
  provider: "pg", // "pg" | "mysql" | "sqlite"
})

Memory (Testing)

import { memoryAdapter } from "@billsdk/memory-adapter";

database: memoryAdapter()

Payment Adapters

Stripe

import { stripePayment } from "@billsdk/stripe";

payment: stripePayment({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
  apiVersion: "2024-11-20.acacia", // Optional
})

Hooks

Execute code before or after every request.

hooks: {
  before: async ({ request, path, method }) => {
    // Return Response to short-circuit
    if (!isAuthenticated(request)) {
      return new Response("Unauthorized", { status: 401 });
    }
    // Return undefined to continue
  },
  after: async ({ request, path, method }) => {
    console.log(`[billing] ${method} ${path}`);
  },
}

Logger

logger: {
  level: "debug", // "debug" | "info" | "warn" | "error"
  disabled: false,
}

On this page