Building the next Uber or Airbnb? The hardest part isn't the appβit's the payments. Here is how to route money from buyers to sellers while keeping your commission.
In a standard SaaS, you collect money from a user. Simple. In a Marketplace, you collect money from a Buyer, take a cut (your fee), and payout the rest to a Seller. This introduces massive complexity: KYC (Know Your Customer) laws, tax reporting, and payout scheduling.
Stripe Connect solves this. It turns your platform into a payment facilitator without the legal nightmare.
For most modern marketplaces (like DoorDash or Lyft), you want Express Accounts. Stripe handles the onboarding UI and tax documents, but you control the experience.
Before a user can sell on your platform, they must have a "Connected Account." You don't create this manually; you generate an onboarding link.
Node.js (Backend)
const stripe = require('stripe')('sk_test_...');
app.post('/onboard-seller', async (req, res) => {
// 1. Create the account
const account = await stripe.accounts.create({
type: 'express',
country: 'US',
email: req.body.email,
capabilities: {
card_payments: {requested: true},
transfers: {requested: true},
},
});
// 2. Create the onboarding link
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: 'https://yourapp.com/reauth',
return_url: 'https://yourapp.com/success',
type: 'account_onboarding',
});
// 3. Send URL to frontend
res.json({ url: accountLink.url });
});
When a buyer purchases an item, you don't just charge them. You create a charge that automatically splits the funds.
Use application_fee_amount to define your cut. The transfer_data tells Stripe where the remaining money goes.
Node.js (Backend)
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [{
price_data: {
currency: 'usd',
product_data: { name: 'Guitar Lessons' },
unit_amount: 10000, // $100.00
},
quantity: 1,
}],
mode: 'payment',
// π‘ THE MAGIC PART
payment_intent_data: {
application_fee_amount: 1000, // You keep $10.00
transfer_data: {
destination: 'acct_12345678', // Seller's Connect ID
},
},
success_url: 'https://yourapp.com/success',
});
Marketplace payments are asynchronous. A seller might disconnect their account, or a payout might fail. You must listen to webhooks to keep your database in sync.
account.updated: Tracks if the seller is fully verified to receive money.payment_intent.succeeded: Confirms the buyer paid.transfer.created: Confirms the seller got their share.