Skip to Content
StackBlaze Templates — operator documentation

Billing

Billing runs on Stripe — checkout for new subscriptions, the hosted customer portal for managing existing ones, and webhooks to keep your database in sync.

The flow

ActionHow
New subscription (free → paid)Stripe Checkout
Manage / switch plan (existing subscriber)Stripe customer portal
Plan state in your DBUpdated by webhooks only

Key routes

RouteRole
app/api/billing/checkoutCreates a Stripe Checkout session.
app/api/billing/portalOpens the customer portal.
app/api/billing/webhookReceives Stripe events and updates the plan.
lib/billing/stripe/*Stripe client + handlers.
lib/billing/plans.tsPlan tiers & prices (source of truth).

The plan only changes when a webhook arrives. Checkout completing in the browser is not enough — the customer.subscription.created / .updated event must reach /api/billing/webhook. If webhooks aren’t wired, real payments succeed but the user’s plan never updates.

Local development

Forward webhooks with the Stripe CLI, bound to your app’s key:

stripe listen --api-key "$STRIPE_SECRET_KEY" \ --forward-to localhost:3000/api/billing/webhook

Copy the printed whsec_… into STRIPE_WEBHOOK_SECRET and restart. Full walkthrough in Your first run.

Production

In production you register the webhook endpoint in the Stripe dashboard and enable the portal’s plan-switching feature once. See Stripe in production.

Changing prices

Edit lib/billing/plans.ts, create matching Stripe prices, and point STRIPE_PRICE_PRO / STRIPE_PRICE_TEAM at the new ids. See Plans & limits.