DEV Community

qing
qing

Posted on

How to Build a Profitable SaaS with Stripe and FastAPI

How to Build a Profitable SaaS with Stripe and FastAPI

How to Build a Profitable SaaS with Stripe and FastAPI

Imagine launching a SaaS product that generates revenue the moment a user clicks “Subscribe.” No manual invoicing, no chasing payments, and no complex billing logic to maintain. With FastAPI for your backend and Stripe for payments, you can build a production-ready billing system in a single afternoon. This isn’t theory—it’s a blueprint you can execute today to turn code into cash.

Why FastAPI and Stripe Are the Perfect Pair

FastAPI is the fastest Python framework for building APIs, offering automatic documentation, async support, and type safety. Stripe provides the most robust payment infrastructure for SaaS, handling subscriptions, recurring billing, and webhook events seamlessly. Together, they eliminate the two biggest hurdles for new SaaS founders: technical complexity and payment reliability.

Unlike older frameworks, FastAPI lets you define endpoints with minimal boilerplate. Stripe’s Python SDK handles the heavy lifting of payment processing, so you focus on your product’s core value.

Step 1: Set Up Your Project Environment

Start by installing the core dependencies. You’ll need FastAPI, Uvicorn (the ASGI server), and Stripe’s official Python library.

pip install fastapi uvicorn stripe python-dotenv
Enter fullscreen mode Exit fullscreen mode

Create a .env file to store your Stripe API keys securely. Hardcoding keys is a security risk; environment variables are the industry standard.

# .env
STRIPE_API_KEY=your_secret_key_here
STRIPE_WEBHOOK_SECRET=your_webhook_secret_here
FASTAPI_HOST=0.0.0.0
FASTAPI_PORT=8000
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Products and Prices in Stripe

Before writing code, model your business in the Stripe Dashboard. You need a Product (what you sell) and a Price (how much and how often).

  1. Go to Stripe Dashboard > Products.
  2. Create a product named “Pro Plan” with a recurring price of $29/month.
  3. Copy the Price ID (e.g., price_1ABC...)—you’ll use this in your API.

This step is critical: Stripe requires a valid Price ID to create checkout sessions. Without it, your API will fail.

Step 3: Build the Checkout Endpoint

Now, let’s create the FastAPI endpoint that generates a Stripe Checkout session. This is the gateway where users enter their payment details.

# main.py
from fastapi import FastAPI, HTTPException
from stripe import CheckoutSession
from dotenv import load_dotenv
import os

load_dotenv()

app = FastAPI()

@app.get("/checkout")
def create_checkout(email: str, price_id: str):
    try:
        session = CheckoutSession.create(
            customer_email=email,
            payment_method_types=["card"],
            line_items=[{"price": price_id, "quantity": 1}],
            mode="subscription",
            success_url=f"{os.getenv('BASE_URL')}/success?session_id={session.id}",
            cancel_url=f"{os.getenv('BASE_URL')}/cancel",
        )
        return {"url": session.url}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
Enter fullscreen mode Exit fullscreen mode

Run your server with:

uvicorn main:app --reload
Enter fullscreen mode Exit fullscreen mode

Visit http://127.0.0.1:8000/checkout?email=user@example.com&price_id=price_1ABC... to test. You’ll get a redirect URL to Stripe’s hosted checkout page.

Step 4: Handle Webhooks for Subscription Status

The checkout page is only half the story. Stripe sends webhooks to notify your backend when a payment succeeds, a subscription cancels, or an invoice fails. You must handle these events to sync your database with Stripe’s state.

Create a webhook endpoint:

from stripe import WebhookSignature, Event

@app.post("/webhook")
def handle_webhook(request: bytes, headers: dict):
    sig_header = headers["stripe-signature"]
    event = None

    try:
        event = WebhookSignature.verify_header(
            request, sig_header, os.getenv("STRIPE_WEBHOOK_SECRET")
        )
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid signature")

    if event.type == "checkout.session.completed":
        # User subscribed: save customer_id and subscription_id to DB
        customer_id = event.data.object.customer
        subscription_id = event.data.object.subscription
        # Update your database here
    elif event.type == "customer.subscription.deleted":
        # User canceled: revoke access
        subscription_id = event.data.object.id
        # Update your database here

    return {"status": "success"}
Enter fullscreen mode Exit fullscreen mode

Crucial: Never rely on the client-side redirect to confirm payment. Webhooks are the only reliable way to verify transactions. Use the Stripe CLI to test events locally:

stripe listen --forward-to localhost:8000/webhook
Enter fullscreen mode Exit fullscreen mode

Step 5: Add Token-Based Authentication for Paying Users

Once a user subscribes, they need access to your API. Implement token-based authentication so only paying users can call your endpoints.

  1. Generate a JWT token after webhook confirmation.
  2. Store the token in the user’s browser.
  3. Require the token in the Authorization header for all API calls.

FastAPI’s HTTPBearer dependency makes this easy:

from fastapi.security import HTTPBearer
from fastapi import Depends

security = HTTPBearer()

def verify_token(token: str = Depends(security)):
    # Validate JWT, check subscription status in DB
    if not is_subscribed(token):
        raise HTTPException(status_code=403, detail="Subscription required")
    return token

@app.get("/api/data")
def get_data(token: str = Depends(verify_token)):
    return {"data": "Premium content"}
Enter fullscreen mode Exit fullscreen mode

Production Deployment Checklist

Before launching, ensure you’ve hardened your system:

  • Switch to live API keys from the Stripe Dashboard (not test mode).
  • Register a live webhook endpoint in Stripe and point it to your domain.
  • Store keys securely using environment variables.
  • Update URLs from localhost to your production domain.
  • Set up monitoring for failed payments and webhook errors (e.g., Sentry).
  • Test end-to-end with a real card in test mode, then a $1 test in live mode.

Refer to Stripe’s Production Deployment Checklist for a complete guide.

Enhance Your SaaS with Advanced Features

Your MVP is ready, but profit comes from scale. Consider these upgrades:

  • Usage-based pricing: Charge per API call or data point.
  • Team billing: Allow multiple users per subscription.
  • Trial periods: Let users try your service for 7 days before paying.
  • Invoicing: Let users download PDF invoices for tax purposes.
  • Analytics: Track revenue, churn, and customer lifetime value.

Stripe’s SaaS integration guide covers these patterns in depth.

Start Building Today

You don’t need a team of engineers or months of development to launch a profitable SaaS. With FastAPI and Stripe, you can build a secure, scalable billing system in hours. The code above is production-ready; plug in your keys, test locally, and deploy to Render, Railway, or Fly.io.

Your first customer is waiting. What’s your SaaS idea? Share it in the comments, and let’s build the future of software together.


If you found this helpful, consider buying me a coffee ☕ — it keeps these articles coming!

Also check out my AI tools collection: AI 次元世界 — free AI tools for developers.


💡 Related: **Content Creator Ultimate Bundle (Save 33%)* — $30*


🛠️ Useful resource: **Content Creator Ultimate Bundle (Save 33%)* — $29.99. Check it out on Gumroad!*

Top comments (0)