Billing & Credits
Plans, checkout, upgrades and downgrades, credit packs, and invoices.
The Billing page is where customers choose and manage what they pay for. Checkout is always hosted by the billing provider — the portal never handles raw card data.
Plan types
Plans are defined in packages/config/src/pricing.ts and synced to the
database. There are three kinds:
| Type | Behavior |
|---|---|
subscription | Recurring monthly or yearly; auto-renews until canceled. |
lifetime | One-time purchase; no expiry, no renewal. |
credit_pack | One-time purchase that adds to a credit balance. |
Checkout flow
Pick a plan
On the Billing page, the customer clicks Upgrade or Change plan and confirms.
Payment + webhook
After payment, the provider posts to /webhooks/billing. The portal verifies
the signature, then updates the subscription, issues a license key, and
grants credits for credit packs.
Return
The customer is redirected to /billing/return, which confirms the subscription
is active and shows the new key.
Changing plans
| Action | When it applies | Charge |
|---|---|---|
| Upgrade | Immediately | Prorated for the rest of the period |
| Downgrade | At period end | Keeps current features until then |
| Cancel | At period end (cancelAtPeriodEnd) | Access continues until the period ends |
If a renewal payment fails, the subscription enters past_due, the provider
retries, and — if all retries fail — the subscription expires and the license
lapses. Customers receive dunning emails during this window.
Credits
Credits let customers exceed a plan's monthly limit without upgrading. When a metered call is made with credit overage allowed and the limit is reached:
Balance is checked
The system looks at the customer's credit balance.
Sufficient → allowed
Credits are deducted and the request proceeds.
Insufficient → denied
The request is rejected with allowed: false.
Every credit movement (purchase, spend, grant, expiry) is written to an immutable ledger, visible in the Billing page's Credits section.
Invoices
An invoice is created for every payment. From the Billing page customers can:
- View every invoice and its status (
paid,open,void,uncollectible) - Download the provider-hosted PDF
Providers & test mode
LemonSqueezy is the default provider; others are available behind the same interface (see Providers). In development, providers run in test/sandbox mode — use the provider's test cards. No real charges are made.
All billing webhooks arrive at a single endpoint — POST /webhooks/billing —
regardless of provider. The signature is verified before anything is processed.