Building Multi-Tenant SaaS with Stripe Connect
A practical walkthrough of designing marketplace billing for a multi-tenant SaaS platform using Stripe Connect, covering account onboarding, fee splitting, and subscription management.
Multi-tenant billing is one of the areas where SaaS architecture gets genuinely hard. You’re not just charging customers — you’re operating a payment marketplace where money flows between your platform and sub-accounts. Stripe Connect is the right tool, but the mental model takes time to internalize.
The Three Account Types
Stripe Connect offers Standard, Express, and Custom connected accounts. For most SaaS platforms where vendors need some control but you want a consistent UX, Express accounts are the right choice.
- Standard: Vendors manage their own Stripe dashboard. Maximum flexibility, minimum control.
- Express: Vendors complete a Stripe-hosted onboarding flow. You control the experience, Stripe handles compliance.
- Custom: You own the entire onboarding and dashboard UX. Maximum control, maximum liability.
Onboarding Flow
The onboarding pattern for Express accounts is:
- Your server creates an Account Link with
account_links.create - Redirect the vendor to the Stripe-hosted onboarding URL
- Stripe redirects back to your
return_urlwith the account ID - Store the
stripe_account_idon your vendor/tenant record - Check
charges_enabledandpayouts_enabledbefore allowing transactions
$accountLink = $stripe->accountLinks->create([
'account' => $vendor->stripe_account_id,
'refresh_url' => route('onboarding.refresh'),
'return_url' => route('onboarding.complete'),
'type' => 'account_onboarding',
]);
return redirect($accountLink->url);
Payment Intents with Application Fees
When a customer pays through your platform, you capture the payment and take a platform fee in a single operation:
$paymentIntent = $stripe->paymentIntents->create([
'amount' => $totalAmount,
'currency' => 'usd',
'application_fee_amount' => $platformFee,
'transfer_data' => [
'destination' => $vendor->stripe_account_id,
],
]);
The application_fee_amount stays with your platform. The remainder transfers to the vendor’s connected account automatically.
Handling Webhooks
Webhooks are where multi-tenant Stripe gets complex. Events can come from your platform account or from connected accounts, and you need to handle both.
Always verify the webhook signature. For connected account events, the account field in the event payload identifies which tenant triggered it.
The Subscription Layer
If your platform has its own subscription tier (vendors pay you monthly), handle that as a separate Stripe Customer on your platform account — completely decoupled from the Connect layer. Mixing the two creates accounting nightmares.
Stripe Connect is powerful, but respect the separation of concerns. Platform billing lives on your account. Marketplace transactions flow through Connect.