Bolt.new has first-class native Stripe integration — add your test key in Settings → Stripe, click 'Retrieve my products', and prompt 'Add payments' to auto-generate checkout and subscription code including Supabase edge functions. Bolt handles the entire setup automatically. Use test card 4242 4242 4242 4242 for development. Deploy to Netlify or Bolt Cloud before testing webhooks, which require a public URL.
Add Payments to Your Bolt.new App with Native Stripe Integration
Stripe is the only payment processor with native first-class support in Bolt.new. While other payment providers require manual API route setup, Stripe connects through a dedicated panel in Bolt's Settings menu. Enter your Stripe API key, click 'Retrieve my products' to sync your Stripe catalog, and then simply prompt Bolt with 'Add payments' — the AI generates a complete checkout or subscription implementation automatically, including Supabase edge functions that handle checkout session creation, webhook processing, and subscription state management.
The native integration requires Supabase or Bolt Database as the backend — Stripe's secret keys and webhook logic run inside Supabase edge functions, keeping sensitive credentials out of client-side code. Bolt handles the Stripe SDK import, checkout session API calls, webhook signature verification, and database updates to track subscription status. What would normally take hours of setup becomes a 10-minute configuration flow.
For development, Stripe's test mode provides a complete sandbox with dedicated test API keys (starting with `sk_test_`) and test card numbers. The canonical test card `4242 4242 4242 4242` with any future expiry date and any CVC triggers a successful payment. Webhooks require a deployed URL — the WebContainer cannot receive incoming HTTP connections — but outbound checkout session creation works fine in the preview, letting you validate your payment UI before deploying.
Integration method
Bolt.new includes a first-class native Stripe integration that auto-generates Supabase edge functions for checkout, subscription management, and webhook processing when you enter your Stripe API key in Settings → Stripe. Unlike most integrations, you don't need to write API route code manually — Bolt's AI generates everything from a simple 'Add payments' prompt. Stripe webhooks require a deployed URL and cannot be tested in Bolt's WebContainer preview.
Prerequisites
- A Stripe account (free to create at stripe.com) with test mode enabled
- Products and prices created in your Stripe Dashboard (can be test mode products)
- A Bolt.new project with Supabase or Bolt Database connected (required for native Stripe integration)
- Supabase project URL and API keys configured in Bolt
- A deployed URL on Netlify or Bolt Cloud for testing webhooks in production
Step-by-step guide
Connect Stripe in Bolt's Settings Panel
Connect Stripe in Bolt's Settings Panel
The Stripe integration in Bolt.new starts in the project Settings, not through a chat prompt. In your Bolt project, click the Settings icon (gear) in the left sidebar or top navigation. Find the 'Stripe' section in Settings. You'll be prompted to enter your Stripe API key. For development, use your test secret key from the Stripe Dashboard — navigate to Stripe Dashboard → Developers → API keys, and copy the key starting with `sk_test_`. Paste it into Bolt's Stripe settings field and save. Once connected, click the 'Retrieve my products' button. Bolt queries your Stripe account and imports all your active products and prices. You'll see them listed with their names, prices, and billing intervals. Select the products you want to use in your app. This sync step is crucial — Bolt uses the real product IDs from your Stripe account when generating checkout code, ensuring the generated code is immediately usable rather than containing placeholder values. You can switch to live keys (`sk_live_`) when you're ready to accept real payments — just replace the key in Settings and re-retrieve products.
Pro tip: Use test mode keys (sk_test_) during development. Bolt's Settings → Stripe panel accepts both test and live keys — never commit either to source control. When switching from test to live, update the key in Settings and redeploy.
Expected result: Bolt shows your Stripe products in the Settings panel, ready to be referenced in checkout prompts.
Prompt Bolt to Add Payments
Prompt Bolt to Add Payments
With Stripe connected and products retrieved, Bolt can now auto-generate the entire payment implementation from a natural language prompt. Type 'Add payments' in the chat, or be more specific about what you need. Bolt generates several files automatically: a Supabase edge function (typically at `supabase/functions/create-checkout/index.ts`) that creates Stripe Checkout sessions using the Stripe Node SDK, a webhook handler edge function (`supabase/functions/stripe-webhook/index.ts`) that verifies Stripe signatures and updates your database, React components for the pricing page and buy buttons, and database tables in Supabase to track customers, subscriptions, and payment status. The AI uses the product IDs retrieved in the previous step to pre-populate the generated code. Review the generated files — specifically the edge function to confirm the product ID and price ID match what you want to sell. If you have multiple products, specify which one in the prompt: 'Add Stripe checkout for the Pro Plan product at $29/month'.
Add Stripe payments to my app. Create a pricing page with a 'Pro Plan' at $29/month. When a logged-in user clicks 'Upgrade to Pro', create a Stripe Checkout session with the subscription price ID from my connected Stripe account. After payment, redirect to /dashboard with a success message. Store the subscription status in Supabase so I can gate premium features. Also set up the webhook handler to update subscription status on renewal, cancellation, and payment failure.
Paste this in Bolt.new chat
1// supabase/functions/create-checkout/index.ts2// Auto-generated by Bolt — review product/price IDs match your Stripe account3import Stripe from 'https://esm.sh/stripe@14.0.0?target=deno';45const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY') ?? '', {6 apiVersion: '2024-04-10',7 httpClient: Stripe.createFetchHttpClient(),8});910const corsHeaders = {11 'Access-Control-Allow-Origin': '*',12 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',13};1415Deno.serve(async (req) => {16 if (req.method === 'OPTIONS') {17 return new Response('ok', { headers: corsHeaders });18 }1920 const { priceId, userId, successUrl, cancelUrl } = await req.json();2122 const session = await stripe.checkout.sessions.create({23 payment_method_types: ['card'],24 mode: 'subscription',25 line_items: [{ price: priceId, quantity: 1 }],26 success_url: successUrl,27 cancel_url: cancelUrl,28 metadata: { userId },29 });3031 return new Response(JSON.stringify({ sessionUrl: session.url }), {32 headers: { ...corsHeaders, 'Content-Type': 'application/json' },33 });34});Pro tip: Bolt generates Supabase edge functions (Deno runtime) for Stripe, not Next.js API routes. This is intentional — edge functions run outside the WebContainer and can safely store your Stripe secret key via Deno.env.get().
Expected result: Bolt generates a pricing page, buy buttons, checkout edge function, webhook handler, and Supabase tables for subscription tracking — all from your prompt.
Test with Stripe Test Cards
Test with Stripe Test Cards
Stripe provides a comprehensive set of test cards that simulate different payment scenarios in test mode. The most important cards: `4242 4242 4242 4242` for a successful payment (use any future expiry, any 3-digit CVC, any ZIP); `4000 0000 0000 0002` for a generic card decline; `4000 0027 6000 3184` to trigger 3D Secure authentication; `4000 0000 0000 9995` to simulate insufficient funds. In Bolt's preview, you can test the checkout flow up to the Stripe Checkout page — the redirect to Stripe's hosted checkout works because it's an outbound HTTP call. Complete the payment with test cards on Stripe's page and verify you're redirected back to your success URL. However, webhook events (payment confirmation, subscription activation) cannot be received in the preview because the WebContainer has no public URL for Stripe to POST to. Test checkout session creation in the preview, but validate the full end-to-end flow including webhooks after deploying. Check the Stripe Dashboard → Events log to see all events generated during testing, even if your webhook handler hasn't processed them yet.
Add a test payment flow to my app. Create a test checkout button on /pricing that triggers a Stripe Checkout session for the first product in my Stripe account. After payment with the test card 4242 4242 4242 4242, redirect to /payment-success and show the order details. Make sure the success URL includes the session_id parameter so I can display the correct order info.
Paste this in Bolt.new chat
1// components/CheckoutButton.tsx2'use client';3import { useState } from 'react';4import { createClient } from '@supabase/supabase-js';56const supabase = createClient(7 process.env.NEXT_PUBLIC_SUPABASE_URL!,8 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!9);1011interface CheckoutButtonProps {12 priceId: string;13 label?: string;14}1516export function CheckoutButton({ priceId, label = 'Subscribe Now' }: CheckoutButtonProps) {17 const [loading, setLoading] = useState(false);1819 async function handleCheckout() {20 setLoading(true);21 const { data: { user } } = await supabase.auth.getUser();2223 const { data, error } = await supabase.functions.invoke('create-checkout', {24 body: {25 priceId,26 userId: user?.id,27 successUrl: `${window.location.origin}/payment-success?session_id={CHECKOUT_SESSION_ID}`,28 cancelUrl: `${window.location.origin}/pricing`,29 },30 });3132 if (error || !data?.sessionUrl) {33 console.error('Checkout error:', error);34 setLoading(false);35 return;36 }3738 window.location.href = data.sessionUrl;39 }4041 return (42 <button43 onClick={handleCheckout}44 disabled={loading}45 className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 disabled:opacity-50"46 >47 {loading ? 'Redirecting...' : label}48 </button>49 );50}Pro tip: Test cards: 4242 4242 4242 4242 (success), 4000 0000 0000 0002 (decline), 4000 0027 6000 3184 (3D Secure). Use any future expiry date and any 3-digit CVC.
Expected result: Clicking the checkout button redirects to Stripe's hosted checkout page. Completing the payment with 4242 4242 4242 4242 redirects back to your success page.
Deploy and Configure Stripe Webhooks
Deploy and Configure Stripe Webhooks
Stripe webhooks are the mechanism by which your app learns about payment events — a subscription was created, a payment succeeded, a subscription was cancelled. During development in Bolt's WebContainer, webhooks cannot be received because the preview URL is dynamic and unreachable from Stripe's servers. To test the complete payment lifecycle including webhooks, deploy your app to Netlify or Bolt Cloud first. Once deployed, go to your Stripe Dashboard → Developers → Webhooks → Add endpoint. Enter your deployed URL with the webhook path: `https://your-app.netlify.app/api/stripe/webhook` (or the path generated by Bolt). Select the events to listen for: `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted`, `invoice.payment_succeeded`, `invoice.payment_failed`. Stripe provides a Webhook Signing Secret — add it to your deployment environment variables as `STRIPE_WEBHOOK_SECRET`. Also add your `STRIPE_SECRET_KEY` as an environment variable in Netlify (Site Configuration → Environment Variables) or Bolt Cloud. The webhook handler Bolt generated uses `constructEventAsync()` to verify the Stripe signature — this is critical for security and must match the correct webhook secret.
Create a Stripe webhook handler at app/api/stripe/webhook/route.ts (or update the Supabase edge function) that verifies the Stripe-Signature header using STRIPE_WEBHOOK_SECRET, handles checkout.session.completed by updating the user's subscription status in Supabase, handles customer.subscription.deleted by downgrading the user to the free plan, and handles invoice.payment_failed by marking the subscription as past_due.
Paste this in Bolt.new chat
1// app/api/stripe/webhook/route.ts2// Alternative Next.js API route (if not using Supabase edge functions)3import { NextRequest, NextResponse } from 'next/server';4import Stripe from 'stripe';56const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {7 apiVersion: '2024-04-10',8});910export async function POST(request: NextRequest) {11 const body = await request.text();12 const signature = request.headers.get('stripe-signature')!;1314 let event: Stripe.Event;1516 try {17 event = stripe.webhooks.constructEvent(18 body,19 signature,20 process.env.STRIPE_WEBHOOK_SECRET!21 );22 } catch (err) {23 console.error('Webhook signature verification failed:', err);24 return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });25 }2627 switch (event.type) {28 case 'checkout.session.completed': {29 const session = event.data.object as Stripe.Checkout.Session;30 const userId = session.metadata?.userId;31 // Update subscription status in database32 console.log('Payment succeeded for user:', userId);33 break;34 }35 case 'customer.subscription.deleted': {36 const subscription = event.data.object as Stripe.Subscription;37 console.log('Subscription cancelled:', subscription.id);38 break;39 }40 case 'invoice.payment_failed': {41 const invoice = event.data.object as Stripe.Invoice;42 console.log('Payment failed for invoice:', invoice.id);43 break;44 }45 }4647 return NextResponse.json({ received: true });48}Pro tip: Stripe requires the raw request body (not parsed JSON) for webhook signature verification. In Next.js, reading the body as text with request.text() before calling constructEvent() is essential — parsing it as JSON first breaks verification.
Expected result: After deploying and registering the webhook, completing a test payment in Stripe triggers the webhook, updates the user's subscription status in Supabase, and gates premium features correctly.
Common use cases
One-Time Product Checkout
Sell a digital product, report, template, or one-time service with a Stripe Checkout page. The user clicks a buy button, completes payment on Stripe's hosted checkout, and is redirected back with a success confirmation. No payment form to build — Stripe handles the entire UI.
Add a one-time payment checkout for my app. When the user clicks 'Buy Now', create a Stripe Checkout session for $49 for the 'Pro Report' product and redirect to Stripe's hosted checkout page. After payment, redirect to /success and show a confirmation message. Use my Stripe test key.
Copy this prompt to try it in Bolt.new
Monthly Subscription with Feature Gating
Let users subscribe to a monthly or annual plan and unlock premium features based on their subscription status. Bolt generates the subscription checkout flow, stores the subscription state in Supabase, and gates feature access based on the user's plan.
Add monthly subscription payments to my app using Stripe. Create a pricing page with Free and Pro plans ($29/month). Clicking 'Upgrade to Pro' creates a Stripe Checkout session with a subscription. After payment, update the user's plan in Supabase and unlock the /dashboard/premium page. Handle the Stripe webhook to update subscription status on renewal and cancellation.
Copy this prompt to try it in Bolt.new
SaaS Per-Seat Billing
Charge teams based on the number of active users using Stripe's quantity-based subscriptions. Each team gets a Stripe customer record, and adding or removing seats adjusts the billing quantity automatically.
Build a team billing system using Stripe subscriptions with per-seat pricing at $15/seat/month. When an admin invites a new team member, increment the Stripe subscription quantity. When a member is removed, decrement it. Show the current billing amount on the Settings page. Use Bolt's native Stripe integration with Supabase.
Copy this prompt to try it in Bolt.new
Troubleshooting
Stripe Checkout session creation fails with 'No such price' error
Cause: The price ID in the generated code doesn't match an actual price in your Stripe account, or you're using a live price ID with a test API key (or vice versa).
Solution: Go to Bolt Settings → Stripe, click 'Retrieve my products' again to resync. Confirm the price ID in the generated edge function matches a price visible in your Stripe Dashboard. Ensure test keys (sk_test_) are used with test price IDs, and live keys (sk_live_) with live price IDs.
Webhook signature verification fails with 'No signatures found matching the expected signature for payload'
Cause: The webhook signing secret does not match, or the request body was parsed as JSON before signature verification (which modifies the raw bytes Stripe uses for signing).
Solution: Read the request body as raw text using request.text() before calling stripe.webhooks.constructEvent(). Verify the STRIPE_WEBHOOK_SECRET environment variable matches the secret shown in Stripe Dashboard → Webhooks → your endpoint → Signing secret. Each webhook endpoint has its own unique secret.
1// CORRECT — use raw text body2const body = await request.text();3event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPE_WEBHOOK_SECRET!);45// WRONG — parsing as JSON breaks verification6// const body = await request.json();Webhook events are not arriving even after deployment
Cause: The webhook endpoint URL in Stripe Dashboard is misconfigured, or the events you need are not selected in the webhook subscription.
Solution: In Stripe Dashboard → Developers → Webhooks, verify the endpoint URL exactly matches your deployed app path. Check that the required events are selected: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_succeeded. Use the 'Send test event' button in Stripe Dashboard to manually trigger a test delivery and check the response.
Bolt shows a 'Stripe requires Supabase' error when trying to add payments
Cause: Bolt's native Stripe integration auto-generates Supabase edge functions, which require a connected Supabase project. If you haven't set up Supabase, Bolt cannot complete the integration.
Solution: Connect Supabase to your Bolt project first: click the database icon in the sidebar, connect an existing Supabase project or create a new one, then return to Settings → Stripe and retry the integration setup.
Best practices
- Use Stripe test mode keys (sk_test_) during all development and staging — only switch to live keys (sk_live_) when deploying to production
- Never put your Stripe secret key (sk_test_ or sk_live_) in client-side code — it belongs in a Supabase edge function or server-side environment variable only
- Always verify webhook signatures using the Stripe-Signature header before processing events — skip this and anyone can send fake payment confirmations to your webhook
- Store the Stripe customer ID alongside your user record in Supabase — you'll need it for subscription management, portal access, and future billing changes
- Handle idempotency in webhook handlers — Stripe may send the same event multiple times, so check if you've already processed an event ID before updating your database
- Test the full payment flow on your deployed URL before going live — webhooks only work on publicly accessible URLs, not in Bolt's WebContainer preview
- Use Stripe's Customer Portal for subscription management (plan changes, payment method updates, cancellation) rather than building these flows yourself
Alternatives
Stripe Connect extends standard Stripe for marketplace and platform payment splitting, where you need to route payments to multiple sellers or service providers.
PayPal is preferred by audiences who distrust entering card details on unfamiliar sites — offering PayPal alongside Stripe can increase checkout conversion.
Adyen is enterprise-grade payment infrastructure used by large-scale platforms that need advanced fraud tools, local payment methods, and direct acquiring.
Square is the go-to choice for businesses with physical retail locations that need unified in-person and online payment processing.
Frequently asked questions
Do I need to write any code to add Stripe payments to my Bolt.new app?
No manual coding is required for the standard setup. Connect Stripe in Settings → Stripe, retrieve your products, then type 'Add payments' in the Bolt chat. The AI generates all the code — checkout edge functions, webhook handlers, pricing pages, and database tables — automatically. You only need to review and potentially customize the generated code.
Can I test Stripe payments in Bolt's WebContainer preview?
You can test the checkout session creation and the redirect to Stripe's hosted checkout page in the preview. However, webhook events (payment confirmation, subscription activation) cannot be received in the preview because the WebContainer has no public URL. Test the checkout flow in the preview, then deploy to Netlify or Bolt Cloud to test the complete webhook-driven payment lifecycle.
Why does Bolt's Stripe integration require Supabase?
Bolt generates Supabase edge functions to handle Stripe's server-side operations — creating checkout sessions, verifying webhook signatures, and storing subscription state. These edge functions run outside the browser and can safely access the Stripe secret key. Without Supabase, there's no secure server-side environment for the secret key to live in.
How do I switch from Stripe test mode to live payments?
Go to Bolt Settings → Stripe and replace your test secret key (sk_test_) with your live secret key (sk_live_). Click 'Retrieve my products' again to sync your live Stripe products. Update your Netlify or Bolt Cloud environment variables to use the live key, and create a new webhook endpoint in the Stripe Dashboard pointing to your production URL with the live signing secret.
Can I offer both one-time payments and subscriptions in the same Bolt app?
Yes. Create separate products in your Stripe Dashboard — one with a one-time price and one with a recurring price. When prompting Bolt, specify both: 'Add a one-time payment for the Starter Report at $49 and a subscription for Pro access at $29/month'. Bolt generates checkout sessions with mode: 'payment' for one-time and mode: 'subscription' for recurring.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation