How to Accept Payments in Bubble.io: Stripe Integration Complete Guide
Stripe billing done correctly runs silently in the background. Done incorrectly, you spend hours every week on manual fixes. The webhook-first architecture, checkout session setup, all six webhook events with their correct handlers, and why you must test every event before launch.
The Complete Stripe Integration From Start to Finish
Adding payment processing to a Bubble.io application is one of the most impactful and most misunderstood parts of building a SaaS. Done correctly, billing runs silently in the background and your product charges customers reliably every month. Done incorrectly, customers who paid have no access, customers who cancelled retain access, and you spend hours every week on manual billing fixes. This guide covers the correct Stripe integration pattern end to end.
The Key Concepts
Stripe is your billing infrastructure
Stripe handles all payment processing, card storage, subscription management, and payouts. Your Bubble app communicates with Stripe via API calls. Never store card data in Bubble.
Webhooks are the source of truth
Stripe sends webhook events to your Bubble app when billing state changes. These events — not the checkout redirect — are what update your database. This is the most important architectural rule in any Stripe integration.
Test mode before live
Every Stripe integration should be built and fully tested in Stripe test mode before switching to live keys. Test mode is free, uses test card numbers, and allows testing all webhook events via the Stripe CLI.
Before Touching Bubble
In your Stripe dashboard, create a Product for each of your subscription tiers. Under each product, create Prices: monthly and annual. Copy the Price ID for each (format: price_XXXX). You will store these in your Bubble Plan data type.
Plan
name
: text (Starter, Growth, Scale)
stripe_price_monthly
: text (price_XXXX)
stripe_price_annual
: text (price_YYYY)
seat_limit
: number (0 = unlimited)
record_limit
: number (0 = unlimited)
trial_days
: number
The Payment Flow
// Step 1: Create Stripe Checkout Session via API Connector
POST https://api.stripe.com/v1/checkout/sessions
customer: Workspace’s stripe_customer_id
line_items[0][price]: Plan’s stripe_price_monthly
line_items[0][quantity]: 1
mode: subscription
trial_period_days: Plan’s trial_days
success_url: https://yourapp.com/billing/success
cancel_url: https://yourapp.com/billing/cancel
metadata[workspace_id]: Workspace’s Unique ID
// Step 2: Redirect user to Stripe’s hosted checkout page
// Step 3: DO NOT update subscription status from the success URL
// Subscription status is updated ONLY by webhooks
The Most Important Part
| Webhook | What to Do | Workspace Update |
|---|---|---|
| checkout.session.completed | Find workspace via metadata[workspace_id]. Set subscription active. | status=Active, stripe_sub_id=event.subscription |
| customer.subscription.updated | Handle plan changes, pauses, and resumes | Update status and plan from event data |
| customer.subscription.deleted | Mark cancelled. Preserve all data. Show reactivation UI. | status=Cancelled, cancelled_at=now |
| invoice.payment_failed | Mark past due. Show urgent payment update banner. | status=Past_Due, payment_failed_at=now |
| invoice.payment_succeeded | Confirm payment. Update billing period end. | status=Active, current_period_end=event date |
| customer.subscription.trial_will_end | Schedule trial-ending email 3 days before expiry | Send upgrade prompt email |
Test Every Webhook With Stripe CLI
Before going live, use the Stripe CLI to test every webhook event: stripe trigger checkout.session.completed, stripe trigger customer.subscription.deleted, etc. Verify that each event correctly updates the Workspace record in your Bubble database. Do not assume it works until you have watched it work.
Build Your Bubble.io App With Expert Help
Pakistan’s leading Bubble.io development team. Multi-tenant SaaS architecture, Stripe billing, and full product builds done right from day one.
