The billing framework
for TypeScript
Define plans and features in code. PayKit handles Stripe, webhooks, and usage state - runs inside your app.
import { feature, plan } from "paykitjs"
const messages = feature({ id: "msgs", type: "metered" })
const proModels = feature({ id: "pros", type: "boolean" })
export const free = plan({
id: "free",
default: true,
includes: [
messages({ limit: 20, reset: "month" }),
],
})
export const pro = plan({
id: "pro",
price: { amount: 19, interval: "month" },
includes: [
messages({ limit: 100, reset: "month" }),
proModels(),
],
})import { stripe } from "@paykitjs/stripe"
import { createPayKit } from "paykitjs"
import { free, pro } from "./products"
export const paykit = createPayKit({
// Any provider: (Stripe / Polar / Creem)
provider: stripe({
secretKey: env.STRIPE_SECRET_KEY,
webhookSecret: env.STRIPE_WEBHOOK_SECRET,
}),
database: env.DATABASE_URL,
products: [free, pro],
on: {
"subscription.activated": ({ customer, plan }) => {
await sendEmail(customer.email, "Welcome to Pro!")
},
}
})How it works
Click around the app below. Every interaction shows the PayKit code that runs and the steps it orchestrates, in real time.
what happens behind the scenes
Features
Everything you need to add billing to your app. Nothing you don't.
Usage billing
Metered features with check() and report(). Zero network latency.
Webhooks handled
Verified, deduplicated, synced to your database automatically.
Any provider
Stripe, Polar, Creem, or your own custom provider. Swap with one import.
Plugins
Extend PayKit with dashboard, analytics, or build your own plugin.
Your database
Billing state in your Postgres, low latency, joinable with your tables.
Type-safe
Plan IDs, feature IDs, events. All inferred from your schema.
Ready to add billing?
One command to get started. Define your plans, connect Stripe, and ship billing in minutes.