---
title: Paykit
description: Billing and entitlements for your product, declared in TypeScript and deployed with your stack.
sidebar:
  label: Overview
  order: 0
---

Paykit is a billing library for TypeScript products. You declare your features,
plans and prices in one file beside your stack. Paykit creates the payment
provider's products and prices at deploy, keeps each account's balances in your
database, and gives your handlers two calls: check and track.

It runs inside your deployment. A check is a local read, so a slow payment
provider cannot block your product, and you do not run a second service to bill.

**New to Paykit?** Start with [What is Paykit?](/what-is-paykit).

## A quick example

Declare a free plan and a paid one:

```ts title="src/catalog.ts"
import { Paykit } from "@potion.run/paykit";

export const messages = Paykit.feature({ id: "messages", name: "Messages" });

export const free = Paykit.plan({
  id: "free",
  name: "Free",
  grants: [Paykit.planItem(messages, { included: 100 })],
});

export const pro = Paykit.plan({
  id: "pro",
  name: "Pro",
  price: { amount: 1900, currency: "usd", interval: "month" },
  grants: [Paykit.planItem(messages, { included: 2_000, overage: "bill" })],
});

export const catalog = { features: [messages], tiers: [free, pro] };
```

The deploy validates the catalog and records it in stack state:

```ts title="alchemy.run.ts"
import { Paykit } from "@potion.run/paykit";
import * as Alchemy from "alchemy";
import * as Effect from "effect/Effect";
import { catalog } from "./src/catalog.ts";

const billing = {
  catalog,
  providers: [Paykit.Manual()],
  store: Paykit.MemoryStore(),
};

export default Alchemy.Stack(
  "MyApp",
  { providers: Paykit.providers(), state: Alchemy.localState() },
  Effect.gen(function* () {
    const recorded = yield* Paykit.BillingStack("Billing", billing);

    return { tiers: recorded.tiers };
  }),
);
```

A request checks before the work and tracks after it:

```ts
const check = yield* Paykit.Check(account);
const { allowed } = yield* check({ featureId: "messages" });

if (!allowed) return refuse();

// do the work

const track = yield* Paykit.TrackUsage(account);
yield* track({ featureId: "messages", value: 1, idempotencyKey: requestId });
```

## Where to start

**Want to build?** [Getting started](/getting-started) takes a catalog through
deploy, a subscription, a check and a track. Then
[Build a billing page](/billing-page) shows the customer their usage and the
upgrade price.

**Looking for a pricing model?** [Pricing models](/concepts/pricing-models) maps
what you sell to the declaration: free plans, usage-based overage, credits,
seats, packs, trials, add-ons and spend limits.

## The docs

**[Concepts](/concepts/pricing-models)**

Pricing models, features, plans, subscriptions, balances and credits.

**[Runtime](/runtime/check)**

The check, the track, holds and commands your handlers call.

**[Build a billing page](/billing-page)**

The pricing table, usage meter, upgrade quote and provider portal.

**[Providers](/providers)**

Stripe, Polar, or an invoice, and the webhooks that confirm a payment.

**[Hosting](/hosting/database)**

The billing database, its migrations, and the session in front of it.

**[Reference](/reference)**

Every tagged public module, generated from the source, and the four packages.

:::tip[The design of record]
The decisions behind this model live in the
[ADRs](https://github.com/potion-run/paykit/tree/main/docs/adr) and
[AGENTS.md](https://github.com/potion-run/paykit/blob/main/AGENTS.md).
:::
