billSDK
Integrations

Next.js

Next.js App Router integration

Route Handler

app/api/billing/[...all]/route.ts
import { billingHandler } from "billsdk/next";
import { billing } from "@/lib/billing";

export const { GET, POST } = billingHandler(billing);

Server Actions

app/actions.ts
"use server";

import { billing } from "@/lib/billing";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";

export async function subscribe(planCode: string) {
  const user = await getCurrentUser();
  
  const result = await billing.api.createSubscription({
    customerId: user.id,
    planCode,
    successUrl: `${process.env.NEXT_PUBLIC_URL}/success`,
    cancelUrl: `${process.env.NEXT_PUBLIC_URL}/pricing`,
  });

  if (result.redirectUrl) redirect(result.redirectUrl);
  revalidatePath("/dashboard");
}

Server Components

app/dashboard/page.tsx
import { billing } from "@/lib/billing";

export default async function DashboardPage() {
  const user = await getCurrentUser();
  const subscription = await billing.api.getSubscription({ customerId: user.id });
  
  return <div>Plan: {subscription?.planCode}</div>;
}

Client Components

For client-side interactivity, use the React hooks.

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

export const billingClient = createBillingClient();

// Re-export hooks for convenience
export const { useCustomer, useSubscription, usePlans } = billingClient;
components/plan-badge.tsx
"use client";

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

export function PlanBadge() {
  const { data: subscription, isLoading } = useSubscription();
  
  if (isLoading) return <span>Loading…</span>;
  return <span>{subscription?.planCode ?? "Free"}</span>;
}

Set the customer ID after authentication:

app/providers.tsx
"use client";

import { useEffect } from "react";
import { billingClient } from "@/lib/billing-client";

export function BillingProvider({ 
  userId, 
  children 
}: { 
  userId: string | null;
  children: React.ReactNode;
}) {
  useEffect(() => {
    billingClient.setCustomerId(userId ?? "");
  }, [userId]);

  return children;
}

Cron for Renewals

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "crons": [
    {
      "path": "/api/billing/renewals",
      "schedule": "0 * * * *"
    }
  ]
}

On this page