0%
Sep 8, 202512 min read

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.

BuildThatMVP.
Stop planning. Start shipping.