Stripe Integration Guide
FastSvelte currently supports subscription-based billing out of the box. One-time payments are on our roadmap and should be straightforward to implement on your own if needed.
Architecture Overview
FastSvelte uses Stripe's Customer Portal for subscription management instead of building a custom billing UI. This approach offers several benefits:
- Security: Stripe handles sensitive payment information and PCI compliance
- Familiarity: Users recognize and trust Stripe's interface
- Less maintenance: No custom billing UI to build or maintain
- Feature-complete: Includes invoice history, payment methods, and subscription management
Webhook-Driven Design
FastSvelte syncs subscription state exclusively through Stripe webhooks. Stripe is the source of truth - all subscription changes happen in Stripe, then Stripe sends webhook events to your backend (/webhook/stripe), which updates your database. FastSvelte never directly modifies subscription data outside of webhook handlers.
Initial Setup
1. Create Stripe Account
- Sign up at stripe.com
- Navigate to your Dashboard
- Create a Sandbox environment for development
Sandbox vs Live Mode
Stripe has two isolated environments:
- **Sandbox** (`sk_test_...`): Development with [test cards](https://stripe.com/docs/testing#cards), no real payments
- **Live Mode** (`sk_live_...`): Production with real payments and customers
Data in each mode is completely separate.
2. Get API Keys
- In your Stripe Dashboard, navigate to Developers → API Keys (or Workbench → API Keys for newer accounts)
- Under "Standard keys", copy your Secret key (starts with
sk_test_for test mode) - Add to
backend/.env:
Security
Secret keys must never be exposed in client-side code or committed to version control.
Publishable Key Not Required
FastSvelte uses Stripe Customer Portal for all payment UI, so you only need the secret key. The publishable key is not needed unless you add custom checkout flows later.
3. Create Products in Stripe
Create your subscription tiers in Stripe:
- Go to Products → Add Product
- Create your subscription tiers (e.g., Free, Pro, Enterprise)
- For the Free tier: Create only a monthly price (FastSvelte auto-provisions this on first login)
- For paid tiers: Create both monthly and annual prices with the same currency
- Copy each Product ID (starts with
prod_)
One Active Subscription Per Customer
FastSvelte maintains one active subscription per customer at a time. When a user signs up, they automatically get the Free tier subscription. Users can then upgrade/downgrade to other tiers through the Stripe Customer Portal.
Don't Want to Offer a Free Tier?
You still need to create a free tier product for auto-provisioning, but you can name it "Default" or something similar. Later, when configuring the Stripe Customer Portal, you can hide this tier from users so it doesn't appear as an option. This allows you to auto-provision users while only showing paid plans.
4. Link Stripe Products to Plans
FastSvelte comes with three plans pre-configured from seed data (Free, Professional, Premium). Configure them through the admin interface:
- Log in as system admin and navigate to
/admin/plans. - You'll see three existing plans from the database seed data
- For each plan, click Edit and add the Stripe Product ID from step 3
- Important: The Free plan (marked as default) must get your free tier's Product ID
!!! warning "Free Plan Requirements" - The plan marked as is_default = true (Free tier) must have a $0 price in Stripe - FastSvelte validates this during auto-provisioning - This plan is automatically assigned to new users on first login
Database Schema
Three tables handle Stripe data:
- `organization.stripe_customer_id` - Links to Stripe Customer
- `plan.stripe_product_id` - Links to Stripe Product
- `organization_plan` - Stores subscription status, period dates, and Stripe subscription ID
5. Configure Stripe Customer Portal
The Customer Portal is where users manage their subscriptions, payment methods, and billing history.
- In Stripe Dashboard, go to Settings → Billing → Customer portal
- Configure Products:
- Under subscriptions enable "customers can switch plans"
- Then add the products (plans) with prices you want to offer for upgrade/downgrade in the portal
- If you want to offer monthly and annual billing, make sure to add both prices for each product
- Configure Features:
- Enable "Customers can update payment methods"
- Enable "Customers can view invoices"
- Optionally enable "Customers can cancel subscriptions" (they'll downgrade to free tier)
- Check out other features and configure as needed
- Save changes
Hiding the Free Tier
If you don't want users to downgrade to the free tier on their own, simply don't add the free tier product to the portal configuration. They can still cancel their paid subscription which will auto-downgrade them to the free tier, but it won't be an explicit option in the portal.
Local Development Setup
1. Install Stripe CLI
Follow the official installation guide for your platform.
2. Authenticate Stripe CLI
- Go to the dashboard URL provided by the CLI
- Select your sandbox account
- Click "Allow access" to authorize the CLI with your Stripe account
This opens your browser to authorize the CLI.
3. Forward Webhooks to Localhost
You'll see output like:
4. Update Webhook Secret
Copy the whsec_ secret and add to backend/.env:
5. Restart Backend
Running Development Environment
Keep two terminals open:
```bash
# Terminal 1: Run backend
cd backend && python -m uvicorn app.main:app --reload
# Terminal 2: Forward webhooks
stripe listen --forward-to localhost:8000/webhook/stripe
```
6. Synchronize Free Subscriptions
In development mode, when you log in for the first time, FastSvelte auto-provisions a free subscription in Stripe. If you logged in before running stripe listen, the webhook won't be received and your database won't sync. To fix this:
- Navigate to
/billingand verify that you see "No subscription found" in the "Current Subscription" section - Click "Manage Subscription" button.
- In the Stripe portal, click "Cancel subscription"
- Then click "Don't cancel" to undo the cancellation
- This triggers a
customer.subscription.updatedwebhook - Go back to
/billingand refresh. You should now see the free subscription details synced from Stripe.
Testing
Test Cards
Use these in Sandbox mode:
| Card Number | Description |
|---|---|
4242 4242 4242 4242 |
Successful payment |
4000 0000 0000 0002 |
Card declined |
4000 0025 0000 3155 |
3D Secure required |
Use any future expiry, any CVC, any postal code.
Production Webhook Setup
Configure Webhook Endpoint
- Go to Stripe Dashboard → Developers → Webhooks
- Click Add Destination
- Select events and continue. FastSvelte listens for three key subscription events:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted- On the next page, select "Webhook endpoint" and Enter your Endpoint URL: `https://api.yourdomain.com/webhooks/stripe
- click "Create endpoint" and you'll see the webhook details page with the signing secret.
- Copy the Signing secret (starts with
whsec_) - Add to production environment:
Production Checklist
Before going live:
- Switch to Live mode (not test/sandbox) in Stripe Dashboard
- Create your products in Live mode with correct pricing
- Verify the free tier product has a $0 price
- Get Live API keys (
sk_live_...) and updateFS_STRIPE_API_KEYin production - Configure webhook endpoint at
https://api.yourdomain.com/webhooks/stripe - Copy live webhook secret to
FS_STRIPE_WEBHOOK_SECRETin production - Update plan records in
/admin/planswith live mode Product IDs - Configure Customer Portal settings in live mode
- Test free tier auto-provisioning with a new signup
- Test complete upgrade flow with a real card
- Set up email notifications for failed payments
- Review tax settings if applicable
- Set up monitoring for webhook failures
Troubleshooting
Missed Webhook During First Login
If you logg up before starting stripe listen, the free subscription exists in Stripe but not in your database. You'll see "No active plan found" warnings in logs and users can't access the billing page.
Quick Fix (Development Only):
- Navigate to
/billingand click "Manage Subscription" - In the Stripe portal, click "Cancel subscription"
- Then click "Don't cancel" to undo the cancellation
- This triggers a
customer.subscription.updatedwebhook - Your database is now synced
Alternative: Find the subscription creation event in your Stripe Dashboard → Events and click "Resend webhook".
Related Documentation
- Development Guide - Local setup
- Deployment - Production deployment
- Integrations - Other integrations