Stack Auth includes a Payments app that handles billing, subscriptions, and one-time purchases through Stripe. Instead of building your own billing system, you define products in the dashboard and Stack Auth takes care of checkout, entitlement tracking, subscription lifecycle, and invoicing. This guide walks through how to set up payments, sell products, manage subscriptions, and work with item-based entitlements like credits or seats.Documentation Index
Fetch the complete documentation index at: https://stackauth-e0affa27-chore-move-mcp-to-a-sep-app.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Getting started
Connect Stripe
Open Payments -> Settings and follow the Stripe Connect onboarding flow. You’ll be asked for business details, bank info, and identity verification. Once approved, payments are live.
Stack Auth Payments is currently only available for US-based businesses. Support for other countries is coming soon.
Core concepts
Before writing any code, it helps to understand how the pieces fit together. A product is something you sell - a subscription plan, a one-time purchase, or a credit pack. Products can have one or more prices (one-time or recurring, in multiple currencies), and they can include items - quantifiable entitlements like credits, seats, or API calls. A product line groups products that are mutually exclusive. For example, a “Plan” product line might contain Free, Pro, and Enterprise - a customer can only have one at a time. When they upgrade, the old plan is replaced. A customer is whoever owns the purchase. This can be a user, a team, or a custom external entity. Here’s how these pieces look in practice: And the typical flow to make it all work:- You define products and items in the dashboard
- Your app generates a checkout URL and redirects the user to Stripe
- The user pays, Stripe notifies Stack Auth, and the product is granted
- Your app reads the customer’s products and item balances to control access
Defining products
Configure your products in Payments -> Products & Items. Each product has:- Display name - What the customer sees
- Customer type - Whether this product is for users, teams, or custom customers
- Prices - One or more prices, each with a currency amount and an optional billing interval (day, week, month, or year). Supported currencies: USD, EUR, GBP, JPY, INR, AUD, CAD.
- Included items - Items granted when the product is purchased, with configurable quantity, repeat schedule, and expiration behavior
- Product lines - Assign products to a product line to make them mutually exclusive (e.g. plan tiers). Configure lines in Payments -> Product Lines.
- Add-ons - Set isAddOnTo to require the customer to already own a specific base product before purchasing this one.
- Free trial - Give customers a trial period before charging. Can be set on the product or on individual prices.
- Include-by-default - Instead of a price, make the product free and automatically available to every customer. Useful for free-tier plans.
- Server-only - Hide the product from client SDK responses. Useful for products that should only be granted programmatically.
- Stackable - Allow multiple purchases of the same product (default is one per customer).
Selling a product
To sell a product, generate a checkout URL and redirect the user to it. ThecreateCheckoutUrl method is available on both user and team objects.
- Client Component
- Server Component
app/components/purchase-button.tsx
createCheckoutUrl on the team object instead:
If you’re using a non-JS backend (Python, Go, etc.), call the REST API directly:
POST /api/v1/payments/purchases/create-purchase-url with customer_type, customer_id, and product_id. See the REST API overview for details.Checking what a customer owns
After a purchase, you’ll want to know what the customer has. There are two ways to do this: check their product list, or check a specific item balance.Listing products
id- The product ID (ornullfor inline products)displayName- The product namequantity- How many the customer owns (relevant for stackable products)type-"one_time"or"subscription"subscription- Subscription details (period end, cancel state) if applicableswitchOptions- Other products in the same product line the customer could switch to
Checking item balances
Items are the building blocks of entitlements. When a product includes items like “100 credits” or “5 seats”, those are tracked as item balances on the customer.quantity- The raw balance (can be negative if you’ve consumed more than granted)nonNegativeQuantity-Math.max(0, quantity)for display purposes
app/components/credits-widget.tsx
Consuming credits (server-side)
When your app needs to consume credits (e.g. when a user sends an AI request), usetryDecreaseQuantity on the server. It’s atomic and race-condition-safe - it will return false and do nothing if the balance would go negative.
lib/credits.ts
Always use
tryDecreaseQuantity() instead of checking the balance and then decreasing. This prevents race conditions where multiple requests could consume more credits than available.credits.increaseQuantity(amount) or decrease without the safety check using credits.decreaseQuantity(amount).
Managing subscriptions
Switching plans
When products belong to the same product line, customers can switch between them. For example, upgrading from Pro to Enterprise:app/components/upgrade-button.tsx
Switching plans requires the customer to have a default payment method saved. The switch happens immediately and Stripe prorates the charge automatically.
Canceling a subscription
cancelSubscription is called on the app instance rather than the user object:
- Client Component
- Server
Billing and payment methods
Customers can save a payment method for future purchases and plan switches. This is built on Stripe’s SetupIntents.Invoices
List a customer’s invoices for displaying billing history:createdAt, status ("draft", "open", "paid", "uncollectible", "void"), amountTotal (in cents), and hostedInvoiceUrl (a link to Stripe’s hosted invoice page).
Invoices support pagination:
Invoices are available for user and team customers only, not custom customers.
Granting products programmatically
Sometimes you need to give a customer a product without going through checkout - free trials, admin grants, promotional offers, etc. UsegrantProduct on the server:
user.grantProduct({ productId }) directly.
Customer types
Stack Auth supports three types of payment customers:- Users - Individual user accounts. Users can manage their own purchases, billing, and invoices from the client SDK.
- Teams - Team or organization accounts. Team admins can create checkouts, switch plans, and cancel subscriptions for their team.
- Custom customers - External entities identified by an arbitrary string ID. Useful for integrations with external systems. Custom customers can only be managed via the server SDK and do not support billing or invoices.
createCheckoutUrl, useProducts, useItem, switchSubscription, useBilling, useInvoices, etc.) are available on both user and team objects. For custom customers, use the top-level stackServerApp methods with customCustomerId.
Dashboard
The dashboard gives you full visibility and control over your payments:- Product Lines - Group products into mutually exclusive tiers. Configure in Payments -> Product Lines.
- Products & Items - Create and edit products, set pricing, and configure included items. In Payments -> Products & Items.
- Customers - View item balances per customer, manually adjust quantities (with optional expiration), and grant products directly. In Payments -> Customers.
- Transactions - See all payment activity, filter by type and customer, view details, and issue refunds. In Payments -> Transactions.
- Payouts - View payout information. In Payments -> Payouts.
- Settings - Connect Stripe, toggle test mode, configure payment methods, and block new purchases. In Payments -> Settings.
Payment emails
Email notifications are sent automatically on payment events:- Payment Receipt - Sent on successful payment with product details, amount, and receipt link
- Payment Failed - Sent on failed payment with product name, amount, and failure reason
Test mode
During development, enable test mode in Payments -> Settings. All purchases will be free and no real money is charged - products are granted immediately without going through Stripe. When you’re ready to test with real Stripe flows (but still using test credentials), disable Stack’s test mode and use Stripe’s test card numbers:- Success:
4242 4242 4242 4242 - Decline:
4000 0000 0000 0002 - Insufficient Funds:
4000 0000 0000 9995