Payments
Stripe subscription billing is fully integrated. Checkout sessions, billing portal, webhook-driven state sync, and automatic customer creation — all working out of the box.
Stripe checkout sessions
Users are redirected to Stripe's hosted checkout page with billing address collection. After payment, a webhook updates the user record and resets the token budget.
- Billing address collection required at checkout
- tRPC creates Stripe Checkout Session server-side
- Redirect to Stripe hosted payment page
- Webhook updates user record on completion
- 1,000,000 token budget reset on new purchases
Billing portal
Stripe's hosted billing portal lets users manage upgrades, downgrades, and cancellations without you building any billing UI.
- Manage subscription upgrades and downgrades
- Cancel subscriptions with Stripe-managed flows
- View invoices and payment history
- Accessible from the account settings page
Webhook-driven state sync
Four Stripe webhook events keep the database in sync with subscription state. Signature verification ensures only legitimate events are processed.
- checkout.session.completed: initial purchase
- customer.subscription.updated: plan changes
- invoice.payment_succeeded: renewals and token budget reset
- customer.subscription.deleted: cancellations
- Stripe signature verification via STRIPE_WEBHOOK_SECRET
Automatic customer creation
A Stripe customer is created automatically in the background when a user signs up. The customer ID is saved to the user record for future billing operations.
- Post-signup hook triggers Stripe customer creation
- stripeCustomerId saved to the user record
- 6 Stripe-related columns tracked: customerId, subscriptionId, priceId, currentPeriodEnd, planActive, planExpires
- Non-blocking creation via waitUntil()
Token budget management
Each subscription comes with a 1,000,000 token budget tracked in Redis. Token usage is decremented after each chat response and reset on renewals.
- 1M token budget per subscription period
- Budget tracked in Redis at chatbot-usage:<userId>
- Decremented after each assistant response
- Reset on invoice.payment_succeeded webhook
- 429 error returned when budget is exhausted
Subscription state tracking
Active subscription statuses include active, trialing, past_due, and incomplete — giving you flexibility in how strictly you gate access.
- Active statuses: active, trialing, past_due, incomplete
- planActive boolean for quick checks
- planExpires tracked for grace period logic
- currentPeriodEnd for renewal date display
Included plans
Plans, pricing, and limits are fully customizable in the codebase. These are the defaults.
Billing that works on day one.
Stripe checkout, webhooks, and budget tracking — already integrated.