If you're building a marketplace, the payment layer is the part that will cost you the most time and hurt the most when it's wrong. Stripe Connect handles the genuinely hard parts (vendor onboarding, compliance, payouts, moving money between parties) but it gives you several ways to structure a payment, and picking the wrong one is expensive to undo once you have live vendors and real transaction history.
This guide covers the decision, not just the API: which charge type to use and why, which account type to onboard vendors into, how to handle webhooks so your ledger stays correct, and the failure modes that only show up once real money is flowing. We've built marketplace payments into production products, and most of what follows is the stuff we wish someone had told us before the first implementation, not after.
Stripe's own documentation is the authority on parameters and current behaviour. Always check it for specifics, since APIs and fees change. What this guide adds is the architectural judgment around it.
First: what problem Connect actually solves
When a customer pays on your marketplace, one payment has to become several. The vendor gets their share, you keep a platform fee, and sometimes a third party (a delivery partner, a second vendor in the same basket, a referrer) takes a cut too. Doing that yourself means holding other people's money, which drags you into money-transmission regulation, KYC obligations, and payout infrastructure. That is a business you almost certainly don't want to be in.
Connect exists so you don't have to be. Stripe onboards your vendors, verifies their identity, holds the regulatory relationship, and moves funds to their bank accounts. Your job shrinks to describing how each payment should be divided, and keeping your own records straight.
That second part, keeping your own records straight, is where most implementations go wrong. Stripe will tell you what happened. Whether your database agrees is your problem.
Choose your charge type before you write any code
This is the decision that's hard to reverse, so make it deliberately. Stripe Connect offers three ways to structure a payment, and they differ in who is legally the merchant, who appears on the customer's card statement, and who eats disputes.
Direct charges. The payment is created on the vendor's connected account. The vendor is the merchant of record, their name shows on the statement, and they bear the dispute liability. Your platform takes an application fee. This suits marketplaces where vendors are established businesses with their own customer relationships, and where you want the vendor to own the transaction, such as a booking platform for independent studios.
Destination charges. The payment is created on your platform account, and Stripe transfers the vendor's share to their connected account. You're the merchant of record, your name is on the statement, and you carry the dispute liability. This is the default for most marketplaces: the customer feels like they bought from your platform, because they did.
Separate charges and transfers. You take the payment onto your platform first, then create transfers to one or more connected accounts afterwards, grouped together so they reconcile. This is the flexible option and the one you need when a single basket spans multiple vendors, when the split isn't known at payment time, or when you need to hold funds before releasing them (escrow-style flows, milestone releases, delivery confirmation).
The practical decision:
| Your situation | Use |
|---|---|
| Vendors own the customer relationship and their brand should be on the statement | Direct charges |
| Your platform is the brand; one vendor per order | Destination charges |
| One order, multiple vendors | Separate charges and transfers |
| Funds must be held until something happens (delivery, approval, milestone) | Separate charges and transfers |
| You're not sure yet | Destination charges: easiest to reason about, and the most common answer |
The question underneath all of this is who is the merchant of record, because that determines who handles disputes. Decide that with your lawyer and your risk appetite, not just your engineer.
Account types: how much of the vendor experience do you want to own?
Separately from charge type, you choose how vendors are onboarded:
- Standard. Vendors get a full Stripe account and dashboard, and manage their own relationship with Stripe. Least work for you, least control over the experience.
- Express. Stripe hosts the onboarding flow and a lightweight vendor dashboard; you keep the surrounding experience. This is the pragmatic default for most marketplaces and the one we reach for first.
- Custom. You build everything, including onboarding UI and vendor-facing payout screens. Maximum control, considerably more work, and you take on more of the compliance surface.
Start with Express unless you have a specific reason not to. You can build a more custom experience later; you cannot easily get back the weeks spent building onboarding UI that Stripe would have hosted for free.
The part teams forget: onboarding is not instantaneous and it is not guaranteed to succeed. A vendor can sign up, start listing, and still not be able to receive money because verification is incomplete. Your product needs a real state machine for this: a vendor is pending, restricted, enabled, or rejected, and your UI has to behave sensibly in each state. Listen for account update events and store the vendor's current capability status. If you skip this, you will eventually take a customer's money for a vendor who cannot be paid, and unwinding that by hand is a bad afternoon.
Webhooks: the part that keeps your ledger honest
Your application cannot know what happened to a payment by hoping. Stripe pushes events to you, and your handling of those events is what keeps your database in agreement with reality.
The events that matter most for marketplace flows:
- Payment succeeded. Credit the vendor's balance in your records, mark the order paid, trigger fulfilment.
- Payment failed. Release any reserved inventory, tell the customer, don't credit anyone.
- Account updated. The vendor's verification or payout capability changed; update their state.
- Transfer created and paid. Funds moved to a vendor; reconcile it against what you expected.
- Charge refunded and dispute events. Money is coming back out; adjust balances and, where relevant, reverse transfers.
Three rules for the handler itself, all of which come from things going wrong:
Verify the signature. An unverified webhook endpoint is an API that lets strangers mark orders as paid. Use Stripe's signature verification; it's a few lines and it is not optional.
Be idempotent. Stripe retries. Network blips, your own 500s, and timeouts all produce duplicate deliveries of the same event. Store processed event IDs and make the handler a no-op on a repeat, otherwise retries turn into double payouts, and you will find out from a vendor rather than from your monitoring.
Acknowledge fast, work asynchronously. Return 200 quickly and push the real work onto a queue. A handler that does slow database writes and calls three internal services inline will eventually time out, which Stripe reads as failure, which triggers a retry, which, if you skipped the previous rule, processes everything twice.
And one that isn't about the handler: reconcile on a schedule. Once a day, compare your ledger against Stripe's record of charges, transfers and payouts, and alert on any divergence. Webhooks are reliable, not infallible; a deploy during an outage window, a bug in one branch of your handler, or a manual refund issued from the Stripe dashboard can all put you out of sync. Marketplaces that discover this at year-end have a much worse time than marketplaces that discover it the next morning.
Refunds, disputes and the money that flows backwards
Every marketplace ships the happy path first and then meets reality. Money going out is harder than money coming in, because the vendor may already have been paid.
The questions to answer before launch, not after:
- When a customer is refunded, does the platform fee get refunded too? You can choose. Decide it as policy, then implement it, and don't let the default decide for you.
- If the vendor's share has already been transferred, are you reversing that transfer, or absorbing the cost and settling with the vendor later?
- What happens when the vendor's connected account doesn't have the balance to cover a reversal?
- Who fights disputes, you or the vendor? This follows from your charge type, and it should be written into your vendor agreement in the same words your code implements.
- How are partial refunds split? A 50% refund on an order with a fixed platform fee is not a 50% reduction in that fee unless you say it is.
None of these are technically hard. All of them are painful to retrofit once you have a year of transactions recorded under an unstated policy.
What actually breaks in production
Beyond the code, the things that reliably cause incidents:
Currency and cross-border payouts. Selling in one currency and paying vendors in another introduces conversion, timing and availability questions. Stripe supports a lot here, but which countries and currencies you can pay out to is a real constraint on which vendors you can onboard. Check it against your expansion plan before you promise a market you can't pay.
Payout timing expectations. Vendors care enormously about when money lands, and the answer involves both Stripe's payout schedule and any hold you impose. Whatever you choose, show it in the vendor dashboard. Most vendor support tickets on a young marketplace are some version of "where is my money", and a visible expected-payout date eliminates most of them.
Testing only the happy path. Use Stripe's test mode and its test cards to force declines, disputes, partial refunds and failed transfers. Run the full onboarding flow as a vendor, including the failure branch where verification is rejected. Deliberately deliver a duplicate webhook and confirm nothing double-counts.
Treating the platform fee as fixed forever. Your take rate will change: promotional rates, tiered rates by volume, per-category rates. If the fee is hardcoded rather than computed from a rule per transaction, and stored on the transaction record as it was applied, changing it later means either a migration or a permanent inability to explain historical numbers. Store what was charged, not just what the current rule says.
What this costs to build
Marketplace payments are one of the more expensive feature areas in a first build, because the surface is wide: onboarding, the charge flow, webhooks, the vendor-facing money UI, refunds, and the admin tooling to fix things by hand when they go wrong.
For real numbers, our e-commerce and marketplace cost guide prices this out by feature at our blended rate, and the MVP cost guide covers what a first marketplace release costs end to end. Our published marketplace tiers run $15,000–$150,000+ depending on how much of the above you need on day one, the honest advice being that most first releases need far less of it than founders assume. A single-vendor-per-order destination charge flow with solid webhooks will carry a marketplace a long way; escrow, multi-vendor baskets and tiered fees can wait for evidence that you need them.
If you're at the architecture stage, our Scoping Sprint is $2,300, fixed, and takes two weeks: you get a clickable prototype, a technical plan that includes the payment architecture decisions above made for your specific model, and a fixed quote for the build. It's credited in full if we build it with you. You can also see how we work on marketplace products and what we've shipped in the portfolio.
Building a marketplace and weighing up the payment architecture? A Scoping Sprint ($2,300, two weeks) ends with these decisions made for your model, a prototype, and a fixed quote, or just start a conversation.


