To integrate Stripe Connect in Bolt.new, prompt the AI to generate a Next.js API route that creates Connect onboarding links and handles account payouts, store your Stripe secret key in the .env file, deploy to Netlify or Bolt Cloud, then register your webhook endpoint with the deployed URL. Stripe Connect enables marketplace and platform payments where third-party sellers get paid through your app.
Build Marketplace Payments in Bolt.new with Stripe Connect
Stripe Connect is the infrastructure layer behind most two-sided marketplaces and platforms — from freelancer platforms to SaaS tools that charge on behalf of their users. Unlike standard Stripe payments where money flows directly to you, Stripe Connect lets you route payments to third-party sellers, take platform fees automatically, and manage payouts across thousands of connected accounts. If you are building anything where money changes hands between your users — a service marketplace, a digital product platform, or a SaaS with revenue sharing — Stripe Connect is the correct tool.
In Bolt.new, the integration follows a clear pattern: Bolt generates the API routes that handle account creation, onboarding redirects, and payment routing. All Stripe secret keys are kept in server-side code, never exposed to the browser. The AI understands Stripe Connect architecture well enough that a single descriptive prompt can scaffold the entire onboarding flow, webhook handler, and frontend redirect logic. The main thing to know before starting is that Stripe Connect involves asynchronous flows — account activation, payment confirmation, and payout events all arrive as webhooks — which means end-to-end testing must happen on a deployed URL, not in Bolt's browser preview.
Bolt's WebContainer runtime blocks incoming connections from the internet, so Stripe cannot send webhook events to your development environment. This is not a bug in Bolt or Stripe — it is a fundamental property of browser-based runtimes. The standard workflow is to build and visually test in Bolt's preview, then do a quick deploy to Netlify or Bolt Cloud (which takes under two minutes) to test webhook-dependent behavior like account activation callbacks and payment confirmation events.
Integration method
Bolt.new integrates with Stripe Connect by generating server-side API routes that handle account creation, onboarding flows, and payment routing. Your Stripe secret key lives in the .env file and is only accessed from server-side code. Because Bolt runs in a WebContainer during development, webhook testing requires deploying to Netlify or Bolt Cloud first.
Prerequisites
- A Stripe account with Connect enabled (free at stripe.com — navigate to Connect in the dashboard to enable it)
- Stripe test API keys: find them under Developers → API keys in your Stripe dashboard
- A Bolt.new project using Next.js (start a new project and ask Bolt to use Next.js if needed)
- A Netlify account for deploying and testing webhooks (free tier is sufficient)
- Basic understanding that Stripe Connect has three account types: Standard, Express, and Custom — Express is recommended for most Bolt projects
Step-by-step guide
Prompt Bolt to scaffold the Stripe Connect integration
Prompt Bolt to scaffold the Stripe Connect integration
Open your Bolt.new project and use the chat to generate the full Stripe Connect integration. Be specific about the account type (Express is simplest for most use cases), the payment flow (Direct charges vs Destination charges), and which webhooks you need. Bolt's AI understands Stripe Connect architecture and will generate the API routes, the onboarding redirect flow, and the React components for your dashboard. For an Express account integration with Direct charges, your prompt should specify: the onboarding flow, the charge creation with application fees, and the webhook handler. Bolt will generate an API route for creating the Connect account, an API route for creating the account link (Stripe's hosted onboarding page URL), and a route for creating payment intents or checkout sessions with the connected account as a parameter. After generating, review the files Bolt created. You should see at minimum: app/api/connect/account/route.ts (creates accounts), app/api/connect/onboard/route.ts (generates onboarding links), and app/api/webhooks/stripe/route.ts (handles events). If Bolt missed any of these, ask it to add the specific missing piece.
Add Stripe Connect to this app using Express accounts. Create these API routes: POST /api/connect/account to create a new Stripe Connect Express account and save the accountId to the database, POST /api/connect/onboard to generate a Stripe account link for onboarding and return the redirect URL, POST /api/connect/checkout to create a payment intent with an application fee routed to the connected account, and POST /api/webhooks/stripe to handle account.updated and payment_intent.succeeded webhook events. Store STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET in .env. Add a seller dashboard page that shows their Stripe account status and earnings.
Paste this in Bolt.new chat
Pro tip: Use Express accounts for marketplaces where sellers don't need full control over their Stripe settings. Express gives you a Stripe-hosted onboarding page which saves significant development time and handles identity verification automatically.
Expected result: Bolt generates the API route files and a seller onboarding component. You will see new files in the app/api/connect/ directory and a dashboard page. The code will reference process.env.STRIPE_SECRET_KEY which does not exist yet — that is expected.
Review the generated API routes and understand the payment flow
Review the generated API routes and understand the payment flow
Before adding your API keys, review the generated code to understand what each route does and verify the payment logic is correct. The three core routes in a Stripe Connect integration each serve a distinct purpose in the payment lifecycle. The account creation route calls stripe.accounts.create() with type: 'express' and saves the returned account ID to your database, associated with your user's record. This account ID is the key that links your user to their Stripe Connect account for all future operations. The onboarding route calls stripe.accountLinks.create() with the account ID, a refresh URL (where to send the user if the link expires), and a return URL (where to send the user after they finish onboarding). This generates a one-time Stripe-hosted URL where the seller completes identity verification and bank account setup. You redirect the user to this URL from your frontend. The checkout or payment route creates a payment intent or checkout session with two additional parameters: the connected account ID (stripe_account) and an application_fee_amount. This tells Stripe to charge the customer, send most of the money to the seller's account, and keep the application_fee_amount on your platform account. Verify the webhook handler calls stripe.webhooks.constructEvent() with the raw request body (not the parsed JSON) and your webhook secret. This signature verification step is critical for security and is a common point of failure if Bolt generates it incorrectly.
1// app/api/connect/account/route.ts2import { NextResponse } from 'next/server';3import Stripe from 'stripe';45const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {6 apiVersion: '2024-11-20.acacia',7});89export async function POST(request: Request) {10 try {11 const { email, userId } = await request.json();1213 // Create a Stripe Connect Express account14 const account = await stripe.accounts.create({15 type: 'express',16 email,17 capabilities: {18 card_payments: { requested: true },19 transfers: { requested: true },20 },21 });2223 // Save account.id to your database associated with userId24 // await db.users.update({ where: { id: userId }, data: { stripeAccountId: account.id } });2526 return NextResponse.json({ accountId: account.id });27 } catch (error) {28 const message = error instanceof Error ? error.message : 'Unknown error';29 return NextResponse.json({ error: message }, { status: 500 });30 }31}3233// app/api/connect/onboard/route.ts34export async function POST(request: Request) {35 const { accountId } = await request.json();36 const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000';3738 const accountLink = await stripe.accountLinks.create({39 account: accountId,40 refresh_url: `${baseUrl}/connect/refresh`,41 return_url: `${baseUrl}/connect/return`,42 type: 'account_onboarding',43 });4445 return NextResponse.json({ url: accountLink.url });46}4748// app/api/connect/checkout/route.ts49export async function POST(request: Request) {50 const { amount, currency, connectedAccountId, platformFeeAmount } =51 await request.json();5253 const paymentIntent = await stripe.paymentIntents.create({54 amount, // in cents55 currency: currency || 'usd',56 application_fee_amount: platformFeeAmount,57 transfer_data: {58 destination: connectedAccountId,59 },60 });6162 return NextResponse.json({ clientSecret: paymentIntent.client_secret });63}Pro tip: The application_fee_amount is taken from the total charge before the remainder is transferred to the connected account. For a $100 charge with a $10 fee, set amount to 10000 and application_fee_amount to 1000 (both in cents).
Expected result: You understand the payment flow: account creation → onboarding link → customer payment with fee routing → webhook confirmation. The code structure matches what Bolt generated, or you have corrected any discrepancies.
Add your Stripe Connect credentials to the .env file
Add your Stripe Connect credentials to the .env file
Stripe Connect requires two credentials during development: your test secret key and, once you have a deployed webhook URL, your webhook signing secret. In Bolt.new, environment variables for server-side code go into the .env file in your project root. Click the file explorer in Bolt and open or create the .env file. Add your Stripe test secret key — it starts with sk_test_. Never use your live key (sk_live_) during development. If Bolt has not already created a .env file, ask it to create one with placeholder values: 'Create a .env file in the project root with STRIPE_SECRET_KEY=your_key_here and STRIPE_WEBHOOK_SECRET=your_webhook_secret_here'. For the NEXT_PUBLIC_BASE_URL variable, set this to http://localhost:3000 during development. When you deploy, you will update this to your Netlify or Bolt Cloud URL. This variable controls where Stripe redirects sellers after the onboarding flow completes. Important: add .env to your .gitignore file if you are pushing to GitHub. Stripe secret keys committed to public repositories get automatically revoked by Stripe's secret scanning system, and you will need to rotate your keys. Bolt's AI typically adds .env to .gitignore automatically, but verify this is the case before any GitHub push.
Create a .env file in the project root with these variables: STRIPE_SECRET_KEY=sk_test_placeholder, STRIPE_WEBHOOK_SECRET=whsec_placeholder, NEXT_PUBLIC_BASE_URL=http://localhost:3000. Make sure .env is in .gitignore. Show me what values I need to fill in and where to find them in the Stripe dashboard.
Paste this in Bolt.new chat
1# .env2# Stripe Connect credentials3# Get these from https://dashboard.stripe.com/test/apikeys4STRIPE_SECRET_KEY=sk_test_your_key_here56# Get this after creating a webhook endpoint in Stripe Dashboard7# Developers → Webhooks → Add endpoint → copy Signing secret8STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here910# Your app's public URL (update after deploying)11NEXT_PUBLIC_BASE_URL=http://localhost:30001213# For Stripe Connect, also needed:14# STRIPE_PUBLISHABLE_KEY for client-side Stripe.js initialization15NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_herePro tip: Stripe Connect requires that you activate your Connect platform in the Stripe Dashboard before creating Express accounts. Go to Dashboard → Connect → Get started and complete the platform profile. Without this step, account creation calls will return errors even in test mode.
Expected result: The .env file exists with your real Stripe test secret key. The app compiles without missing environment variable errors. Bolt's dev server shows no import errors related to Stripe.
Test the onboarding flow in Bolt's preview
Test the onboarding flow in Bolt's preview
With your API key in place, you can test the account creation and onboarding redirect in Bolt's WebContainer preview. The outbound calls from your app to Stripe's API work fine during development — you can create Connect accounts, generate onboarding links, and receive redirect URLs from Stripe. What you cannot test in the preview is webhook delivery, which requires a publicly reachable URL. To test the onboarding flow: navigate to your seller dashboard or onboarding page in Bolt's preview, trigger the 'Connect your Stripe account' action, and verify that Bolt's API route successfully calls stripe.accounts.create() and returns an account ID. Then trigger the onboarding link generation and verify you receive a URL that starts with https://connect.stripe.com/setup/e/. You can click this link and it will take you to Stripe's real onboarding form (in test mode, you can use fake data). For the complete account activation and webhook testing, you need to deploy. Stripe's account.updated webhook fires when a seller completes onboarding, and without receiving this event, your app will not know the account is ready to accept payments. The WebContainer cannot receive this incoming event because browser tabs do not have publicly accessible URLs that Stripe can POST to. If you see CORS errors when making requests to Stripe from client-side code, this means some Stripe calls are being made from the browser instead of the API route. All Stripe API calls using the secret key must go through your server-side routes.
Add a test button on the seller dashboard that triggers the Connect account creation flow and logs the response to the console. I want to verify the API route is working before I deploy.
Paste this in Bolt.new chat
Pro tip: In Stripe's test mode, you can use the test Social Security Number 000-00-0000 and test routing/account numbers to complete the Express account onboarding form without real information.
Expected result: Clicking the onboarding trigger in your app successfully calls the Stripe API, creates a test Connect account, and redirects to Stripe's hosted onboarding page. The browser console shows no errors. The Connect account appears in your Stripe test dashboard under Connect → Accounts.
Deploy to Netlify and register webhook endpoints
Deploy to Netlify and register webhook endpoints
Stripe Connect depends heavily on webhooks for critical events: when a seller completes onboarding (account.updated), when a payment succeeds (payment_intent.succeeded), when a payout is sent (payout.created), and when a charge dispute opens (charge.dispute.created). None of these can be tested locally in Bolt's preview because incoming webhook events require a publicly accessible HTTPS URL. Deploy your app to Netlify first. In Bolt, go to Settings → Applications → Connect Netlify (OAuth authorization), then click Publish. Bolt will build and deploy your app, giving you a URL like your-app.netlify.app. This takes about 60-90 seconds for most Next.js projects. Once deployed, set your environment variables in the Netlify dashboard: Site settings → Environment variables → Add variable. Add STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (you will fill this in next), and NEXT_PUBLIC_BASE_URL set to your Netlify URL. Now register your webhook endpoint in Stripe. Go to Stripe Dashboard → Developers → Webhooks → Add endpoint. Enter your webhook URL: https://your-app.netlify.app/api/webhooks/stripe. Select the events you need: account.updated, payment_intent.succeeded, and checkout.session.completed at minimum. After creating the endpoint, Stripe shows you a Signing secret starting with whsec_. Copy this and add it as STRIPE_WEBHOOK_SECRET in your Netlify environment variables. Trigger a redeploy on Netlify after adding the secret so your app picks it up. Update NEXT_PUBLIC_BASE_URL in your Netlify environment variables to your actual Netlify URL so that Stripe's onboarding redirect URLs point to the correct place after sellers complete their Connect account setup.
Update my Next.js app so the NEXT_PUBLIC_BASE_URL environment variable is used for all Stripe Connect redirect URLs instead of hardcoded localhost. Also make sure the webhook route at /api/webhooks/stripe reads the raw request body (not parsed JSON) before passing it to stripe.webhooks.constructEvent — this is required for webhook signature verification.
Paste this in Bolt.new chat
1// app/api/webhooks/stripe/route.ts2// IMPORTANT: This route must read the RAW body for signature verification3import { NextResponse } from 'next/server';4import Stripe from 'stripe';56const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {7 apiVersion: '2024-11-20.acacia',8});910export async function POST(request: Request) {11 const body = await request.text(); // RAW text, not request.json()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 const message = err instanceof Error ? err.message : 'Unknown error';24 console.error('Webhook signature verification failed:', message);25 return NextResponse.json(26 { error: 'Webhook signature verification failed' },27 { status: 400 }28 );29 }3031 switch (event.type) {32 case 'account.updated': {33 const account = event.data.object as Stripe.Account;34 // Update your database: mark seller account as active if charges_enabled35 if (account.charges_enabled) {36 console.log(`Account ${account.id} is now active and can accept payments`);37 // await db.users.update({ where: { stripeAccountId: account.id }, data: { isActive: true } });38 }39 break;40 }41 case 'payment_intent.succeeded': {42 const paymentIntent = event.data.object as Stripe.PaymentIntent;43 console.log(`Payment ${paymentIntent.id} succeeded for $${paymentIntent.amount / 100}`);44 // Update order status in your database45 break;46 }47 default:48 console.log(`Unhandled event type: ${event.type}`);49 }5051 return NextResponse.json({ received: true });52}Pro tip: After deploying to Netlify, use Stripe's webhook test feature in the dashboard to send test events to your endpoint. Click 'Send test webhook' next to your endpoint and choose account.updated — you should see a 200 response in the Stripe dashboard and the event logged in your Netlify function logs.
Expected result: Your app is live on Netlify. The Stripe webhook endpoint is registered and returning 200 responses to test events. Stripe's Dashboard shows your webhook endpoint as healthy (green checkmark). Seller onboarding completes end-to-end: they click 'Connect account', complete Stripe's form, return to your app, and your database marks their account as active.
Common use cases
Freelancer Marketplace with Seller Onboarding
Build a two-sided marketplace where service providers create Stripe Connect accounts, list their services, and receive payouts after customers pay through your platform. The platform automatically takes a percentage fee on each transaction.
Build a freelancer marketplace with Stripe Connect. When a provider signs up, create a Stripe Connect Express account and redirect them to the Stripe onboarding flow. After onboarding, allow customers to pay for services. Route 90% of the payment to the provider and keep 10% as a platform fee. Handle the account.updated and payment_intent.succeeded webhooks. Use Next.js API routes and store the Stripe secret key in .env.
Copy this prompt to try it in Bolt.new
SaaS Platform with Revenue Sharing
Create a SaaS product where partners or resellers connect their Stripe accounts and receive a revenue share when customers they refer make purchases. The platform dashboard shows each partner their earned payouts.
Create a SaaS partner portal with Stripe Connect. Partners connect their Stripe account using OAuth. When a referred customer pays, split the revenue: 70% goes to the partner as a Stripe transfer, 30% stays on our platform account. Show each partner their total earnings and pending payouts in a dashboard. Use Next.js API routes for all Stripe calls.
Copy this prompt to try it in Bolt.new
Digital Product Marketplace
Build a marketplace for selling digital products where creators upload files, set prices, and customers purchase directly. Payments route to creator accounts instantly with a platform commission deducted automatically.
Build a digital product marketplace with Stripe Connect Direct charges. Creators onboard with a Stripe Express account. When a customer buys a product, charge their card and transfer the sale amount minus a 15% platform fee to the creator's connected account. Show creators their balance and payout history. Add a webhook handler for checkout.session.completed events.
Copy this prompt to try it in Bolt.new
Troubleshooting
Error: 'Your platform profile is not complete' when creating Connect accounts
Cause: Stripe requires you to complete your platform profile in the Connect dashboard before you can create accounts, even in test mode. This is a one-time setup step that many developers skip.
Solution: Go to Stripe Dashboard → Connect → Get started. Fill in your platform name, website URL, and the type of business your platform serves. This takes about 3 minutes. After completing it, your account creation calls will work.
Webhook signature verification fails with 'No signatures found matching the expected signature for payload'
Cause: This almost always means the webhook body is being parsed as JSON before signature verification. Stripe's constructEvent() requires the raw, unparsed request body as a string or Buffer. Next.js API routes parse the body by default in some configurations.
Solution: Ensure your webhook route uses request.text() to read the raw body, not request.json(). The code shown in Step 5 uses the correct pattern. If you are using an older Next.js pages-router pattern, you need to disable body parsing with export const config = { api: { bodyParser: false } }.
1// CORRECT: Read raw body for webhook signature verification2const body = await request.text(); // NOT request.json()3const signature = request.headers.get('stripe-signature')!;4const event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPE_WEBHOOK_SECRET!);Stripe Connect webhook events are not arriving — Netlify function logs show no webhook calls
Cause: Webhooks cannot reach Bolt's WebContainer preview URL because the WebContainer does not have a publicly accessible address. If you registered a preview URL as your webhook endpoint, Stripe cannot deliver events to it.
Solution: Deploy to Netlify or Bolt Cloud first, then register your webhook endpoint using the deployed URL (e.g., https://your-app.netlify.app/api/webhooks/stripe). The WebContainer URL (the *.local.webcontainer-api.io address in your Bolt preview) is not accessible from the internet.
Connected account shows charges_enabled: false even after seller completes onboarding
Cause: In Stripe test mode, accounts do not automatically become fully enabled. You need to use Stripe's test account activation flow or manually activate the account in the test dashboard.
Solution: In Stripe test mode, go to Dashboard → Connect → Accounts, find the test account, and click 'Activate account' to simulate a fully onboarded seller. In production, Stripe activates accounts automatically after identity verification is complete. You can also use Stripe's test onboarding form which has a shortcut to bypass verification.
Best practices
- Always use Express accounts for marketplaces where sellers do not need to customize their Stripe settings — Standard accounts require Stripe OAuth and are significantly more complex to implement
- Store the connected account ID in your database immediately after creation, before redirecting to the onboarding page, in case the seller closes the browser mid-flow
- Set up idempotency keys on payment intent creation to prevent duplicate charges if a network retry causes your API route to be called twice
- Never expose STRIPE_SECRET_KEY in client-side code — all Connect API calls that use the secret key must go through your server-side API routes
- Test with Stripe's test card 4000000000000077 to simulate a declined card and verify your error handling works before going live
- Use Stripe's webhook signature verification on every webhook event — do not process events without verifying the stripe-signature header
- Add a Connect account status check in your dashboard so sellers can see whether their account is active and able to accept payments — poll stripe.accounts.retrieve() or use the account.updated webhook to update this status
- Set up Stripe's automatic payouts schedule (daily or weekly) for your connected accounts rather than manual payouts — this reduces operational overhead and seller support questions
Alternatives
Use standard Stripe if you only need to accept payments for your own business rather than routing money to third-party sellers.
PayPal Payouts is worth considering if your sellers are international and prefer PayPal accounts over Stripe Connect's bank account requirements.
Braintree (owned by PayPal) offers marketplace payments with support for PayPal, Venmo, and cards, though its Connect equivalent requires a custom implementation without a hosted onboarding flow.
Square is a better choice if your marketplace has in-person payment terminals alongside online payments, as Square's hardware integrates with its marketplace API.
Frequently asked questions
Does Bolt.new support Stripe Connect natively?
Bolt.new has a native Stripe integration for standard payments (available via Settings → Stripe), but Stripe Connect for marketplace payments is not part of the native integration and must be implemented manually through API routes. The good news is that Bolt's AI generates Stripe Connect code accurately from a detailed prompt. The manual setup takes about 30 minutes and gives you full control over the payment routing logic.
Can I test Stripe Connect payments in the Bolt.new preview?
You can test outbound API calls — creating accounts, generating onboarding links, and creating payment intents — in Bolt's preview because these are outbound requests from your app to Stripe. What you cannot test in the preview is webhook delivery: Stripe cannot send events like account.updated or payment_intent.succeeded to a Bolt preview URL because the WebContainer does not have a publicly accessible address. Deploy to Netlify or Bolt Cloud to test the full webhook flow.
What is the difference between Direct charges and Destination charges in Stripe Connect?
With Direct charges, the customer's payment appears on the connected account's statement and the connected account is responsible for refunds. With Destination charges, the payment appears on your platform account and you transfer funds to the connected account. For most marketplaces, Destination charges are simpler to implement and give the platform more control. Bolt's AI defaults to Destination charges when prompted — specify 'Direct charges' explicitly if you need the other model.
How do I handle sellers who need to update their bank account after initial onboarding?
Create a new account link using stripe.accountLinks.create() with type: 'account_update' instead of 'account_onboarding'. This generates a fresh Stripe-hosted URL where the seller can update their bank account, identity information, or other settings. The same API route structure from onboarding works — just change the type parameter and add a button in your seller dashboard that regenerates the link on demand.
Will my Stripe Connect integration work when I export the project from Bolt?
Yes. Bolt generates standard TypeScript and Next.js code with no Bolt-specific dependencies. Your API routes, .env configuration, and Stripe SDK usage will work identically in VS Code, on Vercel, or any other Next.js hosting platform. The only adjustment needed is updating the NEXT_PUBLIC_BASE_URL and the webhook endpoint URL registered in Stripe to match your new deployment domain.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation