Back
How to Build SaaS Billing With Stripe: Subscriptions, Trials, Coupons (Guide)

Photo by Tech Daily on Unsplash

How to Build SaaS Billing With Stripe: Subscriptions, Trials, Coupons (Guide)

MT
MVPHub Team
6 min read

How to Build SaaS Billing With Stripe: Subscriptions, Trials, Coupons

Stripe is the gold standard for SaaS billing. But wiring up subscriptions, trials, and coupons correctly takes more than a quick API call. This guide covers the full implementation — from creating products in Stripe to handling every webhook that keeps your app in sync.


Step 1: Set Up Stripe Products and Prices

Before writing code, configure your plans in the Stripe Dashboard:

Create a Product for Each Plan

ProductMonthly PriceAnnual PriceStripe Price ID
Starter$19/mo$190/yrprice_starter_monthly
Pro$49/mo$490/yrprice_pro_monthly
Business$99/mo$990/yrprice_business_monthly

Best practice: Create both monthly and annual prices for each product. Annual plans (with a ~17% discount) improve cash flow and reduce churn.


Step 2: Implement Checkout

Stripe Checkout is a hosted payment page. You create a session, redirect the user, and Stripe handles everything — card entry, validation, 3D Secure, Apple/Google Pay.

Flow:

  1. User clicks "Subscribe" on your pricing page
  2. Your API creates a Stripe Checkout Session
  3. User is redirected to Stripe's hosted checkout
  4. After payment, user is redirected back to your app
  5. Webhook confirms the payment and activates the subscription

Key parameters for the Checkout Session:

  • mode: 'subscription' — for recurring billing
  • customer — attach to an existing Stripe customer (or let Stripe create one)
  • line_items — the price ID(s) the user selected
  • success_url — where to redirect after payment
  • cancel_url — where to redirect if they cancel
  • subscription_data.trial_period_days — to add a free trial

Step 3: Add Free Trials

Trial Without Payment Method

Let users try your product without entering a card. The subscription starts in trialing status. When the trial ends, the subscription becomes past_due if no card is on file.

Best for: Maximizing trial signups (lower friction). Risk: Low conversion if users forget about the trial.

Collect the card during signup but don't charge until the trial ends. This is the standard SaaS pattern.

Best for: Higher conversion rates (card is already on file). Implementation: Set trial_period_days in the Checkout Session and payment_method_collection: 'always'.

Typical Trial Lengths

Product TypeTrial LengthIndustry Standard
Simple tool7 daysCommon
SaaS platform14 daysMost common
Enterprise SaaS30 daysLarge products

Step 4: Implement Coupons and Promotions

Coupon Types

TypeExampleUse Case
Percentage off20% off for 3 monthsMarketing promotions
Fixed amount off$10 off per month for 6 monthsReferral rewards
Free trial extension30-day trial instead of 14Onboarding incentive
100% off for X monthsFree for 3 monthsBeta users, partners

Creating Coupons in Stripe

Create coupons in the Stripe Dashboard or via API. Then create Promotion Codes that users enter at checkout.

Add to Checkout Session: allow_promotion_codes: true — this shows a "Have a promo code?" field on the Stripe Checkout page.


Step 5: Handle Webhooks (Critical)

Webhooks are how Stripe tells your app what happened. Your billing system is broken without webhooks.

Essential Webhook Events

EventAction in Your App
checkout.session.completedCreate subscription record, activate user's plan
invoice.payment_succeededRenew subscription access, update billing date
invoice.payment_failedStart dunning flow, notify user
customer.subscription.updatedHandle plan changes (upgrades/downgrades)
customer.subscription.deletedRevoke access, update user record
customer.subscription.trial_will_endSend "trial ending soon" email (3 days before)

Webhook Security

Always verify webhook signatures:

  1. Get the raw request body (not parsed JSON)
  2. Get the Stripe-Signature header
  3. Use stripe.webhooks.constructEvent() to verify
  4. Only process the event after verification passes

Step 6: Add the Customer Portal

Stripe's Customer Portal lets users manage their own subscriptions:

  • Update payment method
  • View invoices and receipts
  • Change plan (upgrade/downgrade)
  • Cancel subscription

Implementation: Create a portal session and redirect the user. Takes about 10 lines of code. Configure allowed actions in the Stripe Dashboard under Customer Portal settings.


Step 7: Sync Subscription Status

Your database needs a subscription table that stays in sync with Stripe:

FieldSource
userIdYour app
stripeCustomerIdCreated during first checkout
stripeSubscriptionIdFrom checkout.session.completed webhook
stripePriceIdFrom webhook — determines which plan
statustrialing, active, past_due, canceled
currentPeriodEndFrom webhook — when access expires
cancelAtPeriodEndWhether user has scheduled cancellation

Golden rule: Never trust the client. Always check subscription status server-side before granting access to paid features.


Common Mistakes

MistakeConsequenceFix
Not verifying webhook signaturesFake payments, free accessAlways verify signatures
Checking plan status client-side onlyUsers bypass paymentServer-side checks on every request
Not handling invoice.payment_failedUsers lose access silentlyImplement dunning (retry + notify)
Hardcoding price IDsBreaks when prices changeUse environment variables
Not testing with Stripe CLIWebhooks work in production but not locallyUse stripe listen --forward-to

Final Thoughts

SaaS billing with Stripe is a solved problem — but it has many moving parts. Get the checkout flow right, handle webhooks properly, and sync subscription status to your database. Everything else (coupons, trials, portal) is built on that foundation.


Need a billing template? Browse SaaS boilerplates with Stripe built in on MVPHub.

Planning your billing features? Read SaaS Billing Features Checklist.


Working products with full source code — live demo, one-time purchase, instant delivery.

Browse the marketplace
GR LIVEecommerce

Groover Multi-Purpose Store

$149

A fully-polished, multi-purpose e-commerce template engineered for brands that need the full feature set on day one — not a minimal starter you outgrow in a month. Groover ships with a live Medusa-backed catalog, category + collection merchandising, search with multi-facet filtering (category, collection, price, sale, stock, sort), product-detail with variant selection + image gallery + stock messaging + related products, Stripe Elements checkout with provider-aware setup panels, account dashboard with guest order lookup and authenticated order history, customer auth with login/register/logout/profile edit, wishlist with guest browser persistence and signed-in customer sync, blog list + detail, store directory, track-order page, branded 404, About/Contact/FAQ/Terms legal shell, GTM-friendly dataLayer wired into PDP/cards/wishlist/cart/checkout/search, locale + RTL foundation with persistent language switcher, PWA installability baseline, theme switching that applies before hydration and persists in both local storage and cookies, header active-route navigation with live mini-cart summary, skip-link / focus accessibility basics, app-level and route-level loading fallbacks, a recoverable error boundary, generated robots.txt and sitemap.xml, shared SEO metadata helpers, and a Playwright / Vitest / Lighthouse test harness. Every copy string lives in a typed content map so rebranding is a find-and-replace pass, not a code rewrite. Deploy it as-is or use it as the most complete starting point you can buy for a serious storefront.

★★★★★0 soldAstro · Medusa
FU LIVEecommerce

Furniture Store

$49

An elegant furniture and home furnishing e-commerce app with a design-forward Next.js storefront for SEO-optimized product pages and server-rendered category browsing. Alternative framework and mobile ports are available on demand. The visual design emphasizes large product imagery, room-based browsing, and material/color variant selection. Built with Radix UI, shadcn/ui, Tailwind CSS, and Framer Motion for a premium feel. Connects to any headless commerce backend — Medusa JS SDK integration is included. Form handling via React Hook Form with Zod validation ensures robust checkout and account flows. Great for furniture brands, interior design shops, or home decor marketplaces.

★★★★★0 soldExpo · Next.js
PE LIVEecommerce

Perfume Store

$49

A luxury-styled perfume and fragrance e-commerce app built for premium brand presentation. The ready-to-buy Next.js storefront features rich product pages with scent profiles, bottle size variants, gift set options, and server-rendered collections. Mobile, backend, and alternative framework ports are available on demand. The design uses shadcn/ui and Tailwind CSS with an elegant, minimalist aesthetic suited for luxury goods. Easy to customize — swap product data, update branding, and deploy. Perfect for perfume brands, fragrance boutiques, or niche scent marketplaces.

★★★★★0 soldMedusa · Expo

Hand-picked follow-up reading for this guide.

All SaaS articles

Explore other MVP verticals

MVPHub publishes templates and guides for ecommerce, SaaS, marketplaces, AI apps, booking platforms, subscription stores, directory sites, and more. Here are fresh picks from other verticals.