billSDK

Basic Usage

Getting started with BillSDK

After installation, you're ready to create customers and subscriptions.

Customers

A customer represents who pays. Link it to your user system using externalId.

Create Customer

server.ts
import { billing } from "@/lib/billing";

await billing.api.createCustomer({
  externalId: user.id, // your user ID
  email: user.email,
  name: user.name, // optional
});

externalId lets you reference customers by your user ID instead of BillSDK's internal ID.

Get Customer

server.ts
const customer = await billing.api.getCustomer({
  externalId: user.id,
});

Subscriptions

A subscription connects a customer to a plan. Paid plans redirect to Stripe Checkout. Free plans activate immediately.

Create Subscription

actions.ts
import { billing } from "@/lib/billing";
import { redirect } from "next/navigation";

const result = await billing.api.createSubscription({
  customerId: user.id, // externalId or customer.id
  planCode: "pro",
  interval: "monthly", // or "yearly"
  successUrl: "/dashboard",
  cancelUrl: "/pricing",
});

// Paid plans return a Stripe Checkout URL
if (result.redirectUrl) {
  redirect(result.redirectUrl);
}

// Free plans activate immediately (no redirect)

Get Subscription

server.ts
const subscription = await billing.api.getSubscription({
  customerId: user.id,
});

// subscription.status: "active" | "trialing" | "canceled" | "past_due" | ...
// subscription.planCode: "pro"
// subscription.currentPeriodEnd: Date

Change Plan

Upgrades apply immediately with proration. Downgrades take effect at period end.

actions.ts
await billing.api.changeSubscription({
  customerId: user.id,
  newPlanCode: "enterprise",
  newInterval: "yearly", // optional
});

Cancel Subscription

actions.ts
await billing.api.cancelSubscription({
  customerId: user.id,
  cancelAt: "period_end", // keeps access until period ends
});

// Or cancel immediately
await billing.api.cancelSubscription({
  customerId: user.id,
  cancelAt: "immediately",
});

Feature Access

Check if a customer has access to a feature based on their plan.

server.ts
const hasAccess = await billing.api.checkFeature({
  customerId: user.id,
  feature: "api_access",
});

if (!hasAccess) {
  throw new Error("Upgrade to Pro to access the API");
}

Client Side

Use React hooks to access billing data in your components.

lib/billing-client.ts
import { createBillingClient } from "billsdk/react";

export const { useCustomer, useSubscription, usePlans } = createBillingClient();

useSubscription

dashboard.tsx
import { useSubscription } from "@/lib/billing-client";

export function Dashboard() {
  const { data: subscription, isLoading } = useSubscription();

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      <p>Plan: {subscription?.planCode}</p>
      <p>Status: {subscription?.status}</p>
    </div>
  );
}

usePlans

pricing.tsx
import { usePlans } from "@/lib/billing-client";

export function Pricing() {
  const { data: plans } = usePlans();

  return (
    <div>
      {plans?.map((plan) => (
        <div key={plan.code}>
          <h3>{plan.name}</h3>
          <p>${plan.prices[0].amount / 100}/mo</p>
        </div>
      ))}
    </div>
  );
}

Client hooks require the billing route handler to be mounted. See Installation.

Server Side

Use billing.api methods directly on the server. All methods are async.

server.ts
import { billing } from "@/lib/billing";

// In a Server Action or API route
const customer = await billing.api.getCustomer({ externalId: user.id });
const subscription = await billing.api.getSubscription({ customerId: user.id });
const plans = await billing.api.listPlans();

On this page