# How to implement in-app purchases in Bubble.io: Step-by-Step Guide

- Tool: Bubble
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: Starter plan+ (backend workflows for webhook handling)
- Last updated: March 2026

## TL;DR

In-app purchases in Bubble work through a credit or coin system where users buy credits via Stripe Checkout, credits are stored in the User Data Type, and the app deducts credits when users access premium features. This tutorial covers the complete purchase flow from Stripe integration to credit management.

## Overview: In-App Purchases in Bubble

Since Bubble apps run in the browser, traditional mobile in-app purchases do not apply. Instead, you build a credit or virtual currency system where users buy credits via Stripe and spend them on premium features. This pattern works for AI tools, content platforms, marketplace services, and any app with consumable features.

## Before you start

- A Bubble app with user accounts
- A Stripe account configured with the Stripe plugin
- Backend workflows enabled (Starter+)
- Basic understanding of Bubble workflows

## Step-by-step guide

### 1. Design the credit system data structure

Add a field called credits (type: number, default: 0) to the User Data Type. Create a Data Type called CreditTransaction with fields: user (User), amount (number — positive for purchases, negative for usage), description (text), stripe_session_id (text, optional), and Created Date (auto). Create a CreditPackage Option Set with attributes: name (text), credits (number), price_cents (number) — e.g., Starter Pack / 100 credits / 999 ($9.99).

**Expected result:** A credit system with balance tracking, transaction history, and predefined purchase packages.

### 2. Build the credit purchase page with Stripe Checkout

Create a pricing page showing your CreditPackage options in a Repeating Group. Each cell displays the package name, credit amount, and price. The Buy button triggers a workflow that creates a Stripe Checkout session via the Stripe plugin with the package's price. After Stripe redirects back on success, a webhook fires to add credits to the user's account.

**Expected result:** Users can select a credit package and complete purchase through Stripe Checkout.

### 3. Handle the Stripe webhook to add credits

Create a backend API workflow called stripe-webhook. When Stripe sends a checkout.session.completed event, the workflow: (1) Finds the user by their Stripe customer ID or session metadata. (2) Adds the purchased credits to the user's credits field. (3) Creates a CreditTransaction record with a positive amount. (4) Returns a 200 response to Stripe. Configure the webhook URL in your Stripe dashboard.

> Pro tip: Always add credits in the webhook, not in the frontend redirect. The redirect can fail, but webhooks are reliable and retried by Stripe.

**Expected result:** Credits are reliably added to the user's account after successful payment.

### 4. Deduct credits when users access premium features

When a user triggers a premium feature (e.g., generating AI content, downloading a report), add a condition: Only when Current User's credits >= required amount. In the workflow, use Make Changes to Current User to subtract the required credits. Create a CreditTransaction with a negative amount and a description of the feature used. If insufficient credits, show a popup directing them to the purchase page.

**Expected result:** Credits are deducted when premium features are used, with a transaction record created.

### 5. Display the credit balance and transaction history

Show the user's current credit balance in the header or account page: Current User's credits. Build a transaction history page with a Repeating Group of CreditTransactions where user = Current User, sorted by Created Date descending. Each cell shows the date, description, and amount (color-coded: green for positive, red for negative).

**Expected result:** Users can see their credit balance and a history of all purchases and usage.

## Complete code example

File: `Workflow summary`

```text
IN-APP PURCHASE SYSTEM SUMMARY
================================

DATA STRUCTURE:
  User additions: credits (number, default: 0)
  CreditTransaction: user, amount, description, stripe_session_id, Created Date
  CreditPackage (Option Set):
    - Starter: 100 credits, $9.99 (999 cents)
    - Pro: 500 credits, $39.99 (3999 cents)
    - Enterprise: 2000 credits, $99.99 (9999 cents)

PURCHASE WORKFLOW:
  Buy button clicked:
    1. Stripe → Create Checkout Session
       → Line items: package price
       → Metadata: user_id, package_name, credits
       → Success URL: /purchase-success
       → Cancel URL: /pricing
    2. Redirect to Stripe Checkout

WEBHOOK (backend workflow: stripe-webhook):
  Event: checkout.session.completed
  Actions:
    1. Find user from session metadata
    2. Make Changes to User: credits + package credits
    3. Create CreditTransaction (positive amount)
    4. Return 200

CREDIT DEDUCTION (premium feature button):
  Condition: Only when Current User's credits >= 10
  Actions:
    1. Make Changes to Current User: credits - 10
    2. Create CreditTransaction: amount=-10, description="AI generation"
    3. Execute the premium feature
  If insufficient:
    → Show popup: "You need more credits. [Buy Credits]"

BALANCE DISPLAY:
  Header: "[Current User's credits] credits"
  Transaction history: RG of CreditTransactions, sorted by date desc
```

## Common mistakes

- **Adding credits on the Stripe redirect instead of the webhook** — The redirect can fail if the user closes the browser or loses connection. Credits would not be added even though payment succeeded. Fix: Always add credits in the Stripe webhook handler, which is reliable and retried by Stripe if your server does not respond.
- **Not checking credit balance before deducting** — Without a balance check, users could use features they have not paid for, resulting in negative credit balances Fix: Add an Only When condition checking Current User's credits >= required amount before the deduction action
- **Not recording credit transactions** — Without a transaction log, you cannot audit purchases, track usage patterns, or resolve customer disputes Fix: Create a CreditTransaction record for every purchase and every deduction with descriptive details

## Best practices

- Process credit additions via Stripe webhooks, not frontend redirects
- Always check credit balance before deducting to prevent negative balances
- Record every credit change as a CreditTransaction for auditing
- Show the credit balance prominently so users know their remaining credits
- Offer multiple credit packages at different price points
- Send a low-balance email notification when credits drop below a threshold

## Frequently asked questions

### Can I offer a subscription instead of credits?

Yes. Use Stripe subscriptions with a recurring billing cycle. Store the subscription status on the User and check it for feature access instead of credit balances.

### How do I handle refunds?

Create a backend workflow triggered by Stripe's charge.refunded webhook. Deduct the refunded credits from the user's balance and create a negative CreditTransaction.

### Can I give free credits to new users?

Yes. In your signup workflow, set credits to a starter amount (e.g., 10 free credits) and create a CreditTransaction with description 'Welcome bonus'.

### Do credits expire?

Not by default. If you want expiring credits, add an expiry_date field to CreditTransaction and build a scheduled workflow that removes expired credits.

### How do I prevent credit fraud?

Always process credit additions server-side via Stripe webhooks, never from the frontend. Use Stripe's signature verification. Validate all credit deductions server-side. RapidDev can help build fraud-resistant payment systems.

### Can I sell credits for different feature categories?

Yes. Create separate credit types (e.g., AI credits, download credits) with separate balance fields, or use a single currency and vary the cost per feature.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/implement-in-app-purchases-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/implement-in-app-purchases-in-bubble
