Stripe Connect
TL;DR: Stripe Connect handles marketplace payments, but setup is tricky. Use Express accounts for speed, Custom for control. Avoid the 14 mistakes that break compliance.
Get payments right from day one. Fixing payment systems later is expensive.
Why Stripe Connect (Not Regular Stripe)
Regular Stripe problem: You receive all payments, then manually pay out sellers/providers Legal issues: You're holding other people's money, tax complications, compliance risks Business problems: Manual payouts, angry sellers, accounting nightmares
Stripe Connect solution:
- ✅ Direct payments to sellers (you never hold their money)
- ✅ Automatic tax handling (1099s, etc.)
- ✅ Platform fees automatically collected
- ✅ Dispute/refund handling
- ✅ Built-in compliance
When you need Connect:
- Marketplace (buyers pay sellers, you take a fee)
- Service platform (clients pay providers)
- Multi-vendor anything
- Anyone who needs to pay other people
The 3 Connect Account Types
Express Accounts (Recommended for MVPs)
Best for: Fast MVP launch, simple marketplaces Pros:
- 5-minute setup for sellers
- Stripe handles compliance and onboarding
- Mobile-friendly signup flow
- Built-in fraud protection
Cons:
- Less customization
- Stripe branding in seller flow
- Limited control over experience
Use cases: Freelance platforms, simple marketplaces, service booking
Custom Accounts
Best for: Full control, branded experience Pros:
- Complete customization
- Your branding throughout
- Advanced features and controls
- Better conversion rates
Cons:
- Complex compliance requirements
- More development work
- You handle support issues
Use cases: Large marketplaces, complex payment flows, enterprise
Standard Accounts
Best for: Rare edge cases Limited use: When sellers need full Stripe dashboards Usually avoid: Express or Custom are better choices
Express Accounts: The MVP Choice
Setup Flow (30 minutes):
1. Create Connect Account
const account = await stripe.accounts.create({
type: "express",
country: "US",
email: "seller@example.com",
capabilities: {
card_payments: { requested: true },
transfers: { requested: true },
},
})
2. Generate Account Link
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: "https://yourapp.com/reauth",
return_url: "https://yourapp.com/return",
type: "account_onboarding",
})
// Redirect seller to accountLink.url
3. Check Onboarding Status
const account = await stripe.accounts.retrieve("acct_123")
if (account.charges_enabled && account.payouts_enabled) {
// Ready to accept payments
}
Payment Flow:
1. Create Payment Intent
const paymentIntent = await stripe.paymentIntents.create({
amount: 10000, // $100.00
currency: "usd",
application_fee_amount: 1000, // $10.00 platform fee
transfer_data: {
destination: "acct_seller123",
},
})
2. Collect Payment (Frontend)
// Seller receives $90, you get $10 fee
const { error } = await stripe.confirmCardPayment(paymentIntent.client_secret, {
payment_method: "pm_card_visa",
})
The 14 Common Mistakes
1. Wrong Account Type Choice
Mistake: Using Custom for MVPs or Express for complex needs Fix: Express for speed, Custom for control - match your actual requirements
2. Missing Capability Requests
Mistake: Not requesting transfers capability
Symptom: Can collect payments but can't pay sellers
Fix: Always request both card_payments
and transfers
3. Forgetting Application Fees
Mistake: Setting up payments without platform fees
Problem: No revenue model built into payment flow
Fix: Always specify application_fee_amount
4. Webhook Ignorance
Mistake: Not handling Stripe webhooks properly
Symptoms: Users stuck in weird states, payments not updating
Fix: Handle these events: account.updated
, payment_intent.succeeded
, payout.created
5. Express Link Expiration
Mistake: Not handling expired onboarding links Symptom: Sellers can't complete signup Fix: Create new links when old ones expire (7 days)
6. Tax Documentation Assumptions
Mistake: Assuming Stripe handles all tax requirements Reality: You still need proper business classification Fix: Understand your marketplace's tax obligations
7. Refund Handling
Mistake: Not planning for refunds and disputes Problem: Who pays fees when refunds happen? Fix: Decide policy upfront: platform absorbs or splits costs
8. International Complexity
Mistake: Adding international sellers without understanding compliance Issues: Different banking requirements, tax rules, payout timing Fix: Start domestic, expand internationally carefully
9. Minimum Payout Thresholds
Mistake: Not setting reasonable payout minimums Problem: Lots of small payouts eat into margins Standard: $25-50 minimum payout threshold
10. Account Status Monitoring
Mistake: Not checking if sellers can actually receive payments
Issue: Accounts can be restricted after onboarding
Fix: Check charges_enabled
and payouts_enabled
before payments
11. Pricing Structure Complexity
Mistake: Complex fee structures that don't map to Stripe Problem: Application fees are fixed amounts, not percentages of percentages Keep simple: Fixed fee or simple percentage
12. Connect Platform Fee Mistakes
Stripe's fees: 2.9% + 30¢ + 0.25% for Connect Your fees: Subtract from application_fee_amount Don't double-charge: Users pay Stripe fees + your fees, not Stripe fees on your fees
13. Dashboard Access Confusion
Express: Sellers get basic dashboard access Custom: You control everything, sellers see what you show them Don't mix: Be clear about who handles what support
14. Compliance Shortcuts
Mistake: Ignoring terms of service and compliance requirements Risk: Account suspension, legal issues Required: Proper terms, privacy policy, business model disclosure
Sample Implementation: Service Marketplace
1. Database Schema
-- Sellers table
CREATE TABLE sellers (
id SERIAL PRIMARY KEY,
stripe_account_id VARCHAR,
onboarding_completed BOOLEAN DEFAULT FALSE,
charges_enabled BOOLEAN DEFAULT FALSE,
payouts_enabled BOOLEAN DEFAULT FALSE
);
-- Bookings table
CREATE TABLE bookings (
id SERIAL PRIMARY KEY,
seller_id INTEGER REFERENCES sellers(id),
amount INTEGER, -- in cents
platform_fee INTEGER, -- in cents
stripe_payment_intent_id VARCHAR,
status VARCHAR DEFAULT 'pending'
);
2. Seller Onboarding Flow
// Create Connect account
app.post("/sellers/onboard", async (req, res) => {
const account = await stripe.accounts.create({
type: "express",
country: "US",
email: req.body.email,
capabilities: {
card_payments: { requested: true },
transfers: { requested: true },
},
})
// Save to database
await db.query("INSERT INTO sellers (stripe_account_id) VALUES ($1)", [account.id])
// Generate onboarding link
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: "https://yourapp.com/seller/reauth",
return_url: "https://yourapp.com/seller/dashboard",
type: "account_onboarding",
})
res.json({ onboarding_url: accountLink.url })
})
3. Payment Processing
app.post("/bookings/:id/pay", async (req, res) => {
const booking = await getBooking(req.params.id)
const seller = await getSeller(booking.seller_id)
// Check seller can receive payments
const account = await stripe.accounts.retrieve(seller.stripe_account_id)
if (!account.charges_enabled || !account.payouts_enabled) {
return res.status(400).json({ error: "Seller not ready for payments" })
}
// Create payment intent
const paymentIntent = await stripe.paymentIntents.create({
amount: booking.amount,
currency: "usd",
application_fee_amount: booking.platform_fee,
transfer_data: {
destination: seller.stripe_account_id,
},
metadata: {
booking_id: booking.id,
},
})
res.json({
client_secret: paymentIntent.client_secret,
})
})
4. Webhook Handling
app.post("/webhooks/stripe", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["stripe-signature"]
const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET)
switch (event.type) {
case "account.updated":
// Update seller status in database
updateSellerStatus(event.data.object)
break
case "payment_intent.succeeded":
// Mark booking as paid
updateBookingStatus(event.data.object.metadata.booking_id, "paid")
break
case "application_fee.refunded":
// Handle refund logic
handleRefund(event.data.object)
break
}
res.status(200).send("OK")
})
Pricing Strategy for Connect
Platform Fee Models:
Percentage Model:
- Take 5-15% of transaction value
- Easy to understand and scale
- Aligns incentives (you win when sellers win)
Fixed Fee Model:
- $1-5 per transaction
- Better for high-value transactions
- Predictable for sellers
Hybrid Model:
- Small percentage + fixed fee
- Example: 3% + $0.50
- Covers your costs while staying competitive
Stripe Costs to Account For:
- Card processing: 2.9% + 30¢
- Connect fee: Additional 0.25%
- Express accounts: No additional platform fees
- Custom accounts: Additional complexity = higher effective costs
Competitive Analysis:
- Uber/Airbnb: 3-5% platform fee
- Stripe Connect marketplaces: Average 2-8%
- Industry specific: Research your vertical's standards
Launch Checklist
Pre-Launch (Technical):
- [ ] Connect account creation flow
- [ ] Seller onboarding with Express accounts
- [ ] Payment processing with application fees
- [ ] Webhook endpoint handling key events
- [ ] Database schema for tracking accounts/payments
- [ ] Error handling for failed payments
Pre-Launch (Legal/Compliance):
- [ ] Terms of service mentioning marketplace model
- [ ] Privacy policy covering data sharing with Stripe
- [ ] Seller agreement outlining fee structure
- [ ] Refund/dispute policy
- [ ] Tax documentation plan (1099s, etc.)
Post-Launch (Monitoring):
- [ ] Dashboard showing payment volumes and fees
- [ ] Seller account status monitoring
- [ ] Failed payment tracking and retry logic
- [ ] Customer support process for payment issues
FAQ
Q: How long does seller onboarding take? A: Express accounts: 5-15 minutes for most sellers. Custom accounts: Can require additional documentation.
Q: What happens if a seller's account gets suspended? A: They can't receive new payments, but existing payments in transit still process. You need backup payment methods.
Q: Can I change fee structures later? A: Yes, but only for new transactions. Existing payment intents use their original fee structure.
Q: How do refunds work with application fees? A: By default, you keep the application fee when refunds happen. You can choose to refund your fee too.
Ready to build marketplace payments?
We implement Stripe Connect properly so your sellers get paid and your platform stays compliant.
Quick Build ($750) • Full Sprint ($7,500)
Internal links:
Ready to get started properly?
Don't wing the fundamentals. Set up legal, technical, and business foundations that investors expect.
More Getting Started
Delaware C-Corp + Founder Docs
Set up your Delaware C-Corp properly from day one. Essential documents, equity splits, and legal foundations that scale. Complete founder checklist.
Terms/Refunds/Disputes
Protect your startup with proper terms of service, refund policies, and dispute processes. Templates and frameworks that actually work.