Table of Contents
Adding payments isn’t just “connect Stripe.” If you’ve done it before, you already know what you're signing up for:
Handling tokens securely without storing card data
Managing trials, subscriptions, cancellations, refunds
Syncing payment status with your app (gated access, upgrades, downgrades)
Setting up Stripe webhooks and handling edge cases
Keeping your billing logic, app logic, and user data all in sync
Doing it without breaking stuff—or wasting a week on backend setup
Stripe solves the infrastructure side, but it still assumes you’ll wire up a backend around it.
Bubble fills that gap. With Bubble’s visual workflows, you can trigger logic based on payment actions, store Stripe data in your app’s database, and control user access all without writing backend code.
And the best part? You don’t need custom endpoints, Stripe.js, or raw API calls to make it work.
This post walks through the simplest, most reliable way to integrate Stripe with your Bubble app using Bubble’s official Stripe plugin.
We’re not covering advanced builds like the Stripe.js plugin, custom payment pages, or raw API flows. If you just want one-time payments or subscriptions working fast and clean, the Bubble plugin is more than enough.
Let’s break down how it works
What You Need Before You Start
Before you integrate Stripe with Bubble, make sure these four pieces are ready.
You won’t need to write any code—but skipping a step here can cost you time later.
1. A Bubble app
Head to bubble.io, create a new app, and start with a blank canvas.
You can use either the development or live version. Bubble will handle the right Stripe keys for each environment automatically.
2. A Stripe account
Go to stripe.com and sign up (or log in).
Once inside:
Go to Developers → API Keys
Copy your Test Publishable Key
Copy your Test Secret Key

You’ll paste both into Bubble later.
Stick with test keys for now. Stripe lets you simulate real payment flows using fake cards (which we’ll cover shortly).
3. Set Up Your Pricing in Stripe
Before building anything in Bubble, get clear on your billing model.
Stripe can handle one-time charges, subscriptions, trials, metered usage—you name it. But you need to define what you're building for upfront.
Think of this step as creating your products in Stripe, not in Bubble.
You’ll want to set this up if:
You’re using Stripe Checkout
You’re offering subscriptions
You want to send invoices or support multiple pricing tiers
You care about clean reporting inside your Stripe dashboard
If you're only doing one-off charges in Bubble (like charging a custom amount without a predefined product), you can technically skip this.
But for most apps, creating Products and Prices in Stripe keeps your setup clean, trackable, and scalable.
4. Create a Product and Price in Stripe
To start charging users through Bubble, you’ll need to set up a Product and at least one Price in Stripe.
Step-by-step:
Go to your Stripe Dashboard
Click “+ Add product”
Give it a clear name like “Pro Plan” or “Template License”
Description is optional, but helpful for internal tracking
Under Pricing, click “Add price”
Choose One-time for a single charge (e.g. a digital download)
Choose Recurring for subscriptions (monthly, yearly, etc.)
Set your price (e.g. $19.00)
If recurring, choose the billing interval
Want free trials or tiered pricing?
Stripe handles those inside the Price object - you won’t need workarounds in Bubble.
Example:
Product: Premium Plan
Prices:
$19/month
$190/year
$1 trial (one-time or recurring with a trial period)
Stripe will generate a Price ID like price_1OabcXYZ...
This is the ID you’ll use in Bubble when triggering:
Subscribe the user to a plan
Start a Stripe Checkout session

Pro tip: Don’t hardcode prices in Bubble.
Store the Stripe Price ID in your database and reference it in workflows. That way, pricing updates only happen in Stripe, not across your app logic.
If you're planning multiple pricing tiers, set them all up now. A solid Stripe structure makes your Bubble workflows simpler and easier to scale.
Install the Stripe Plugin in Bubble
To connect Stripe with your Bubble app, install the official plugin and add your test keys.

Steps:
Open your Bubble app
Go to the Plugins tab
Click Add plugins
Search for “Stripe”
Choose the official plugin by Bubble and click Install
Paste in your Test Publishable Key and Test Secret Key
Test keys start with pk_test_
, sk_test_
Live keys start with pk_live_
, sk_live_
Bubble automatically switches between test and live mode depending on whether your app is in Dev or Live.
Just make sure to start with test keys. Add live keys only when you're ready to launch.
Redirects with Stripe Checkout
If you're using Stripe Checkout (Stripe’s hosted payment page), you can control where users go after a successful or cancelled payment by setting redirect URLs in your workflows.
For example:
After success :
https://yourapp.bubbleapps.io/success
After cancel :
https://yourapp.bubbleapps.io/cancel

You can also manage redirects using Bubble workflows.
But setting these URLs as fallbacks ensures users still land in the right place if your logic ever breaks.
What the Plugin Gives You
Once installed, the Stripe plugin adds three key actions to your workflow editor under the Plugins section:
Charge the current user : for one-time payments
Subscribe the user to a plan : for recurring billing
Collect the user’s card details : for saving a payment method
These actions are the foundation of your payment flows in Bubble.
With your app, Stripe account, pricing setup, and plugin ready, you're all set to start building the actual payment flow.
Creating Payment Workflows in Bubble
Using Stripe Checkout (Recommended for Simplicity)
Once your Stripe plugin is installed and your Product/Price is set up, you’re ready to trigger real payments from your Bubble app.
The simplest way is to use Stripe Checkout — a hosted payment page managed entirely by Stripe.
No need to design your own checkout UI, handle card data, or manage redirects manually. Stripe handles it all.
Here’s how to set it up in Bubble:
1. Add a Button to Trigger the Payment
In the Design tab:
Drag a Button onto your page
Label it something like “Subscribe Now” or “Buy for $49”
2. Create a Workflow for That Button
Click the button
Go to Start/Edit Workflow
Add an action:
Plugins → Subscribe the user to a plan (for recurring billing)
or Plugins → Charge the current user (for one-time payments)
Choose based on your pricing model:
Use Subscribe the user to a plan if you created a recurring price in Stripe
Use Charge the current user for a one-time payment setup
3. Configure the Action
For Subscribe the user to a plan:
Select the Price from the dropdown (Bubble pulls your Stripe prices automatically)
Choose “Collect the user’s CC info via Stripe Checkout”
If the user doesn’t have a payment method saved, they’ll be redirected to Stripe Checkout
Set up success and cancel handling through workflows:
Redirect users to a success or cancel page
Or show messages and trigger custom actions based on payment outcome
Optional: You can also pass metadata into Stripe (e.g., user ID, plan type) for easier tracking and reporting.
4. Test the Flow
Preview your app in Dev mode
Click the button → You’ll be redirected to Stripe Checkout
Use a test card like
4242 4242 4242 4242
Complete the payment
After payment, Stripe will either:
Redirect the user to your defined success or cancel URL
Or trigger any post-payment workflows you've defined in Bubble
If the payment is successful, Bubble will:
Run any post-checkout workflows (e.g., set user’s plan to “pro”, show confirmation message)
Save the user’s Stripe Customer ID and Subscription ID to the Bubble user object, which you can use later for billing or access checks
What About More Advanced Setups?
The official Bubble Stripe plugin is perfect for most SaaS, membership, and digital product use cases:
One-time payments
Subscriptions
Free trials
Simple checkout flows via Stripe Checkout
It’s fast, secure, and exactly what most builders need to get started.
But if you need more advanced billing logic, like custom checkout UIs, saved cards, multi-vendor payouts, or usage-based billing, you’ll eventually hit the limits.
Option 1: Custom Payment Flows via API Connector
If Stripe Checkout doesn't give you enough control (e.g. dynamic metadata, full UI customization), you can go straight to Stripe's API using Bubble’s API Connector.
This gives you access to Stripe’s full API, including:
Creating custom Checkout Sessions or Payment Intents
Saving cards for future use
Cancelling or upgrading subscriptions
Usage-based or metered billing
Dynamic amounts and metadata tracking
But it comes with tradeoffs:
You’ll need to define each API call manually
Handle webhooks using Bubble backend workflows or external tools
Map Bubble user data to Stripe objects yourself
Stripe API Docs | CheckoutSession API
Option 2: Use the Stripe.js Plugin (by @copilot)
Stripe.js is a powerful community plugin that brings most of Stripe’s features into Bubble — no raw API calls needed.
It’s ideal for apps that need:
Custom checkout UIs
In-app billing and saved cards
Stripe Connect for marketplaces
Split payments and payouts
If you’re building something like Airbnb, Upwork, or any multi-party platform, Stripe.js is the tool to use.
Comparison: Stripe Options in Bubble
TL;DR
Just want to charge users or start subscriptions fast? Use the Bubble Stripe plugin
Need saved cards, in-app billing, or marketplace features? Go with Stripe.js
Need full control and Stripe-native logic? Use the API Connector
Feature / Use Case | Bubble Stripe Plugin | Stripe.js Plugin | Custom API (API Connector) |
Setup difficulty | Easy | Moderate | Advanced |
One-time payments | Yes | Yes | Yes |
Subscriptions | Yes | Yes | Yes |
Stripe Checkout (hosted page) | Built-in | No | Requires API call |
Custom payment UI | No | Yes | Yes |
Saved cards | Limited | Yes | Yes |
Marketplaces (Stripe Connect) | Yes | Yes | Yes |
Add metadata (e.g. user ID) | No | Yes | Yes |
Webhook support | Optional | Recommended | Required |
Best for... | Simple SaaS / MVPs | Custom billing / marketplaces | Full control / large apps |
Handling Subscriptions in Bubble
If your product runs on monthly or yearly plans, Stripe’s subscription model paired with Bubble’s plugin makes setup pretty straightforward.
You’ll use Stripe Checkout to start the subscription, and Bubble to control what happens next.
Basic Setup: Start a Subscription
1. Create a subscription price in Stripe
Go to Products → Add product
Name it something like “Pro Plan”
Under Pricing, select Recurring
Choose a billing interval (monthly, yearly, etc.)
Click Save and copy the Price ID
You’ll use this ID in your Bubble workflow.
2. Add a “Subscribe” button in Bubble
In the Bubble editor:
Drag a Button onto your pricing page
Label it something like “Subscribe Now”
Click the button → Start/Edit Workflow
3. Trigger the subscription in your workflow
Action: Plugins → Subscribe the user to a plan
Choose your Stripe price from the dropdown list
Bubble handles the Stripe Checkout redirect and subscription creation behind the scenes.
4. Handle the post-payment experience
If the payment succeeds, Bubble will:
Automatically update the user object with subscription details
Continue the workflow steps you’ve defined
Show a confirmation message
Redirect to the user dashboard
Trigger onboarding steps, etc.
Going Further: More Control & Best Practices
Once basic billing is in place, here’s how to make your subscription flow more robust:
Store the Stripe Subscription ID
After a user subscribes:
Use the session_id from the URL
Call the Checkout Session API
Extract and store the Subscription ID on the user
This gives you better visibility and enables subscription management later.
Set a plan_expiration_date manually (if no webhooks)
If you’re not using webhooks:
Set a field like plan_expiration_date = Current date/time + 30 days
Use this to trigger reminders, grace periods, or content locking when the date passes
Not as reliable as webhooks, but helpful for simple setups.
Use conditionals for feature gating
Gate content based on the user’s plan or expiration status:
Only show premium content when:
Current User's Plan Price ID is "price_..."Only allow access when:
plan_expiration_date > Current date/time
Subscriptions can get complex fast, but with Bubble’s plugin and a bit of structure, you can manage most SaaS billing needs with minimal friction.
Handling Webhooks: Keeping Bubble in Sync with Stripe
Stripe handles billing on its side, but Bubble won’t automatically know when:
A user cancels their subscription
A payment fails
A subscription renews or expires
To fix that, you’ll need to set up a Stripe webhook, a way for Stripe to notify your Bubble app when something changes.
What We're Doing
Stripe triggers a webhook event (e.g. subscription canceled)
We catch that event using Bubble’s backend workflows (or via Make/Zapier)
We parse the data (e.g.
event_type
,customer_id
)We find the matching Bubble user
We update their plan, status, or expiration date
Using Bubble’s Native Backend Workflows (Recommended)
This gives you the cleanest integration, but requires a paid Bubble plan with Backend Workflows enabled.
What You’ll Need:
A Stripe account
A Bubble app with Backend Workflows turned on
Bubble users must store the Stripe Customer ID or Subscription ID
A webhook endpoint that listens to Stripe events
Step 1: Enable Backend Workflows in Bubble
Go to Settings → API
Check “Enable Workflow API and Backend Workflows”
You’ll now see Backend Workflows in the left panel
Step 2: Create a New API Workflow /stripe-webhook
In Backend Workflows, click New API Workflow
Name it:
stripe-webhook
Set it to “Detect Request Data”
This lets Bubble automatically capture incoming webhook data and map fields like:
customer_id
subscription_id
event_type
You can also manually parse the full payload by accepting the entire request body as a single object.
Step 3: Add Logic to Handle Events
Inside your workflow:
Find the user where
Stripe Customer ID = customer_id
from the webhookIf found, add conditions based on the
event_type
Examples:
Event Type | Action |
| Set user’s plan to “free”, lock access, notify user |
| Flag user, show alert, or start a grace period |
| Extend access, reset expiration, or confirm subscription |
Step 4: Set Up the Webhook in Stripe
Go to Stripe Dashboard → Developers → Webhooks
Click “+ Add endpoint”
URL:
https://yourapp.bubbleapps.io/api/1.1/wf/stripe-webhook/initialize
(The/initialize
helps Bubble detect the structure on the first request)Choose events to listen for (e.g.
invoice.paid
,invoice.payment_failed
,customer.subscription.deleted
)Click Save
Once your webhook fires and Bubble captures the request, remove /initialize
from the URL so Stripe sends real events directly to:
https://yourapp.bubbleapps.io/api/1.1/wf/stripe-webhook
Testing Your Webhook Setup
Option 1: Use Stripe CLI (Recommended for Dev)
stripe listen --forward-to https://yourapp.bubbleapps.io/api/1.1/wf/stripe-webhook/initialize
Then simulate an event:
stripe trigger invoice.payment_failed
Check Bubble logs under Logs → Server Logs
Make sure your webhook ran and the workflow logic triggered properly.
Option 2: Use the Stripe Dashboard
Go to Developers → Webhooks → Your Endpoint
Click “Send test webhook”
Choose a test event like
invoice.paid
Click Send test webhook
Make sure your test user in Bubble has the exact Stripe Customer ID that the test webhook sends, otherwise, nothing will update.
Testing Payments in Bubble

Before going live, test your full payment flows in Stripe’s test mode. It behaves exactly like production, but no real money is involved.
Use Case | Test Card Number |
Basic success |
|
Payment declined |
|
3D Secure flow |
|
Full list of test cards: Stripe test card docs
How to Test in Bubble
Make sure your test keys are entered in the Stripe plugin
Preview your app in Dev mode
Trigger a payment or subscription flow
Complete checkout using a test card
Bubble should:
Redirect to your success URL or trigger your defined success workflow
Run any post-payment workflows (e.g. set user’s plan, show confirmation)
Update the user’s data (e.g. Stripe Customer ID, subscription status)
Test Your Webhooks (Optional but Recommended)
Use the Stripe CLI to simulate events and confirm your backend workflows are wired up correctly:
stripe listen --forward-to https://yourapp.bubbleapps.io/api/1.1/wf/stripe-webhook
stripe trigger invoice.payment_failed
This helps you QA your webhook logic - cancellations, failed payments, renewals - before anything goes live.
Test mode is totally safe.
You can click through full payment flows, trigger real-looking emails, and even simulate edge cases without touching real money or users.
Going Live

Stripe makes switching to live mode easy, but small mistakes here can block real payments.
Pre-launch checklist:
Replace test keys with live keys
Go to Stripe Dashboard → Developers → API Keys
Copy
pk_live_...
andsk_live_...
Paste them into the Live fields of the Stripe plugin in Bubble
Don’t delete your test keys
You'll need them later for testing edge cases.Switch your plugin to live mode
Bubble automatically uses the live keys when you deploy, but check your workflows — especially if you hardcoded price IDs or built custom flows.Use HTTPS
Stripe won’t process live payments over HTTP.In Bubble: Settings → Domain/Email → Check "Enable SSL"
Verify your Stripe account
Go to the Stripe Dashboard and check for any alerts:Business info
Identity verification
Banking setup

Double-check currency, tax, and branding
Set your default currency, statement descriptor, and tax settings while you’re there.
Let Users Manage Their Own Billing (Stripe Customer Portal)
If you don’t want to build a billing UI from scratch, Stripe has you covered.
Step 1: Enable the billing portal
Stripe Dashboard → Settings → Billing → Customer Portal
Click Configure, then choose:
Cancel subscriptions
Update payment methods
Switch plans
View billing history
Save
Step 2: Trigger the portal from Bubble
Use the API Connector:
POST https://api.stripe.com/v1/billing_portal/sessions
{
"customer": "cus_abc123",
"return_url": "https://yourapp.bubbleapps.io/account"
}
Stripe returns a URL, redirect the user to that.
Step 3: Add a "Manage Subscription" button
In your UI, place a button under account settings → trigger the API call → redirect to the portal.
Customizing Stripe Checkout
Even though it’s hosted, Stripe Checkout gives you solid control.
Add your branding
Stripe Dashboard → Branding
Customize:
Logo (128×128px PNG)
Brand color
Accent color
Statement descriptor (bank label)
Enable more payment methods
Go to Settings → Payment Methods to activate:
Apple Pay / Google Pay
SEPA, iDEAL, Bancontact
Klarna, Affirm
Link (save card for faster checkout)
You must have a verified account and supported region for these.
Set default language and currency
Settings → Checkout Settings
Choose default locale and currency
Enable test mode previews
Customize Checkout Sessions (for API Connector / Stripe.js)
You can add:
customer_email
mode
: payment or subscriptionpayment_method_types[]
allow_promotion_codes: true
metadata
: for tagging sessions
Discounts and Promo Codes
Stripe supports coupons out of the box — no extra logic needed.
Create a Coupon
Stripe Dashboard → Products → Coupons → New
Choose:
% off
Fixed amount
Duration (once, forever, or N months)
Create a Promotion Code
Products → Promotion Codes → New
Link it to your coupon
Set code (e.g.,
LAUNCH20
)Optional: set expiration, usage limits, or customer restrictions
Enable promo codes in Checkout
Just set allow_promotion_codes: true
in your Checkout Session.
Supported natively in the official Bubble Stripe plugin
Works for one-time and subscription payments
Can be tested in test mode
Common Pitfalls & Pro Tips
Build an internal billing panel
Quick access = fewer support headaches.
Include:
Stripe Customer ID
Plan and subscription status
Start and next billing dates
Cancel button (manual trigger)
Link to view in Stripe
Hide it on a protected admin page
Webhook syncing is critical
Your Bubble app isn’t the source of truth — Stripe is.
Set up webhooks for:
invoice.paid
invoice.payment_failed
customer.subscription.deleted
Forward to Bubble backend workflows (or Make/Zapier)
Update plan, expiration, and status accordingly
Most Stripe logic breaks 30 days later, not on day one.
Handle plan upgrades and cancellations cleanly
Stripe handles proration. You need to reflect changes in your app.
Let users choose new plans
Trigger plan switches via Checkout or custom API calls
Be transparent: show messaging like “Plan will change on next billing cycle”
Never hide downgrade or cancel options — it leads to chargebacks
Show billing status in your UI
Clear visibility builds trust. Always display:
Current plan
Subscription status (active, trialing, canceled)
Next billing date
End date (if canceled)
Use Current User's plan ID
, plan_expiration_date
, and Bubble conditionals to manage access reliably.
Add a “Manage Billing” button if you don’t have a custom flow
Let Stripe handle changes via the billing portal. Fast, safe, and no-code.
Log Key Billing Events
Logging saves your future self (and your support team).
Set up a simple Billing Logs
data type and track:
Event type
User
Timestamp
Notes (e.g., “subscription canceled via webhook”)
Log:
Subscriptions created
Payments failed
Cancellations
Downgrades
Webhook triggers
If this feels like a lot to implement, we get it.
We're a Bubble.io Gold Agency that helps SaaS teams and founders integrate Stripe the right way — without drowning in edge cases.
Let’s build it together.