Installation
how to install and configure PayKit in your app
Steps
Install the package
Let's start by adding PayKit to your project:
pnpm add paykitjsCreate the PayKit instance
Create a file named paykit.ts anywhere in your app.
Usually you would put it somewhere in src/, src/lib/.
Import createPayKit and export your paykit instance. This is the main server entry point
for all billing.
import { createPayKit } from "paykitjs";
export const paykit = createPayKit({
// ...
});Configure Stripe
PayKit uses Stripe for billing. Pass your Stripe keys directly to the PayKit instance.
export const paykit = createPayKit({
// ...
stripe: {
secretKey: process.env.STRIPE_SECRET_KEY!,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
},
});Configure database
PayKit needs a database to store billing state, such as subscriptions. You can create a separate database, or simply plug it into the app's own db.
Pass a connection string directly, or pg.Pool.
import { Pool } from "pg";
export const paykit = createPayKit({
// ...
database: new Pool({
connectionString: process.env.DATABASE_URL!,
}),
});It works by creating a few tables prefixed with paykit_. You can learn more here.
Mount request handler
To handle webhooks and client API requests, you need to set up a request handler on your server.
Create a new file or route in your framework's designated catch-all route handler. This route should handle requests for the path /paykit/* (unless you've configured a different base path).
import { paykitHandler } from "paykitjs/handlers/next";
import { paykit } from "@/lib/paykit";
export const { GET, POST } = paykitHandler(paykit);Create client instance
The client-side library helps you interact with the server. PayKit client sdk suitable for almost all modern frameworks, including React.
import { createPayKitClient } from "paykitjs/client";
import type { paykit } from "@/server/paykit";
export const paykitClient = createPayKitClient<typeof paykit>();To use client we also need to authenticate incoming requests on the server, to do this, add the identify option to your server instance.
export const paykit = createPayKit({
// ...
identify: async ({ headers }) => {
const session = await auth.api.getSession({ headers });
if (!session) return null;
return {
customerId: session.user.id,
email: session.user.email,
name: session.user.name,
// Just pass user's data, and Stripe customer gets synced automatically!
};
},
});Define your products
Optionally. PayKit provides a code-first way to create your plans, and a very useful usage billing with track() and report() out of the box.
By defining you products in code don't have to touch Stripe's dashboard at all. It automatically syncs your pricing with your provider, and you unlock a full type-safety with inferred ID types!
import { feature, plan } from "paykitjs";
const messages = feature({ id: "messages", type: "metered" });
const proModels = feature({ id: "pro_models", type: "boolean" });
export const free = plan({
id: "free",
name: "Free",
group: "base",
default: true,
includes: [
messages({ limit: 100, reset: "month" })
],
});
export const pro = plan({
id: "pro",
name: "Pro",
group: "base",
price: { amount: 19, interval: "month" },
includes: [
messages({ limit: 2000, reset: "month" }),
proModels()
],
});Then pass your products to the main options:
import { free, pro } from "./products";
export const paykit = createPayKit({
// ...
products: [free, pro],
});This is an example setup for AI chat app. Read further on how to build your own billing config.
Push changes to DB
PayKit includes a CLI tool to keep your database in sync with your configuration.
pnpm dlx paykitjs pushThis applies database migrations and syncs your plan definitions to provider's
products.
Run it once on setup, and every time after you change your products configuration.
For production deployments, see the CLI reference.