Why Marketplace Escrow Is Harder Than It Looks
The marketplace escrow problem tends to surface at the worst possible moment: a buyer complains that goods never arrived, a seller insists they shipped, and someone is wrong — or lying. Without controlled fund flow, the platform is caught between refunding the buyer and absorbing the loss, or leaving the buyer furious. Neither outcome is a viable business.
Marketplace escrow means holding payment until a condition is met — delivery confirmed, service completed, inspection passed. The concept is simple. The implementation is not.
Stripe Connect is the dominant infrastructure for this pattern in custom-built marketplaces. It is not a regulated escrow product — Stripe is explicit about this distinction — but it provides enough primitives to build escrow-like behavior: charge the buyer immediately, hold funds on the platform account, then transfer to the seller when a trigger condition fires. This piece covers how that flow actually works, where it breaks down, and what tradeoffs to make before you launch.
How Stripe Connect Creates the Escrow Window
Stripe Connect has three integration models: Standard, Express, and Custom. For marketplaces that need control over fund timing, Express or Custom with destination charges is the right path.
The key insight is separating the charge from the transfer. In a destination charge:
- Buyer pays → funds land on your platform Stripe account
- Transfer to the seller happens separately, triggered by your application code
- Your platform fee is taken at either step
That gap between steps 1 and 3 is your escrow window. You can hold funds for hours, days, or weeks depending on your release conditions. Stripe does not impose a hard cap on hold duration, but anything beyond 60–90 days starts attracting compliance scrutiny, and your sellers will object well before then.
The practical setup: create a PaymentIntent with transfer_data[destination] pointing to the seller's connected account, but delay creating the Transfer until your release condition fires. Alternatively, you can use capture_method: manual to authorize without capturing — but this only stays open for 7 days and suits reservations better than general escrow. For most marketplace escrow use cases, capture immediately and delay the transfer.
Triggering the Release: What Counts as Done?
This is where marketplace logic gets highly specific to your domain, and where most teams underestimate complexity. The release trigger depends entirely on your category:
- Physical goods: Auto-release after N days from confirmed delivery, or immediately on buyer confirmation — whichever comes first
- Service marketplace: Release when the buyer marks work complete, or auto-release N days after the seller marks it delivered
- Rental marketplace: Release after checkout date plus an inspection window
- B2B procurement: Release on purchase order match or invoice approval
Whatever the trigger, you need three things working together:
- A state machine for each transaction — at minimum:
pending,delivered,released,disputed,refunded - A scheduled job that auto-releases when no action is taken — silent buyers are the majority
- A webhook handler for seller-pushed status changes (marked shipped, marked delivered, etc.)
The auto-release timer is non-optional. If buyers can stall payment indefinitely by doing nothing, sellers will leave the platform. Typical windows run 3–7 days for digital goods, 7–14 for physical, and longer for high-value services. Set this based on your category's dispute window, not on what feels generous to buyers.
Platform Disputes vs. Stripe Chargebacks
These are two different problems that get conflated constantly.
Platform disputes are internal: the buyer says the item didn't arrive; the seller says it shipped. You mediate and decide who gets the money. If you side with the buyer before the seller has been paid, you refund from your platform account. If the seller has already been transferred funds, you can reverse that transfer — but only up to the available balance in their Stripe account. If they have already withdrawn, you have a collections problem, not a Stripe problem.
Stripe chargebacks are external: the buyer contacts their card issuer directly. Stripe notifies you, and you have 7–21 days to submit evidence. With destination charges, default chargeback liability sits on your platform account, not the seller's. You can recoup this from sellers by deducting from future earnings or reserve balances, but that needs to be in your terms of service before the first chargeback arrives — not added as a retroactive response to fraud.
The practical implication: you cannot fully insulate your platform from chargeback exposure. If a seller commits fraud at scale before you catch it, the liability lands on your platform first. Stripe monitors platforms for dispute rates — breaching 0.75% for Visa triggers their monitoring program and eventually account restrictions. This is one of the less-obvious reasons why supply-side vetting matters even when your instinct is to focus entirely on buyer experience.
Seller Reserves: The Underused Safety Valve
Holding a portion of seller earnings in reserve is one of the most practical risk tools available, and most early-stage marketplaces skip it entirely.
Stripe Express and Custom accounts support configurable payout schedules. You can configure a reserve percentage — say, 5–10% of each transaction — held back for 30 days before releasing to the seller. This creates a buffer for dispute resolution without requiring you to claw money back from someone's bank account after the fact.
The operational tradeoff: sellers notice this immediately, and it directly affects their cash flow. Communicate it clearly during onboarding, price it into their expectations, and ideally tie it to trust milestones — the reserve percentage decreases after 90 days of clean transaction history. Treated as a policy rather than a penalty, most professional sellers accept it. Announced retroactively after they are already active, it creates churn.
Partial Releases and the Edge Cases That Break Flows
Clean escrow logic assumes clean transactions. Real marketplaces have neither:
Partial delivery: Buyer receives part of an order. An all-or-nothing release model forces an adversarial dispute. A better design offers partial release — Stripe supports partial transfers and partial refunds simultaneously, so there is no technical obstacle. The obstacle is your own UI and state machine handling it.
Cancellations before capture: If using capture_method: manual, cancel the PaymentIntent and nothing hits the buyer's card. Post-capture cancellations become refunds, with settlement delay and potentially different fee treatment depending on whether the charge has already settled.
Seller-initiated cancellations: Issue a full refund to the buyer, update order state, and if the seller has already received a partial transfer, reverse it. Also send notifications to both parties — don't make buyers discover the cancellation from a Stripe receipt email.
Unresolvable disputes: Sometimes neither side is clearly right. Build a human review queue early — a simple internal admin view showing orders in disputed state with the ability to resolve in either direction. Your ops team should not be updating the database directly, and every disputed transaction should not become a Stripe support ticket.
Tradeoffs to Make Before Launch
| Decision | Option A | Option B |
|---|---|---|
| Charge model | Destination charges | Separate charges + transfers |
| Release trigger | Buyer confirmation | Time-based auto-release only |
| Chargeback liability | Platform absorbs | Clawback from seller earnings |
| Seller reserves | Hold % for N days | No reserve (rely on vetting) |
| Dispute resolution | Automated rules | Human review queue |
Neither column is universally correct. Lower-volume, higher-trust marketplaces — B2B services, professional networks — tend toward human review with generous windows. High-volume, low-AOV marketplaces need automation and tight timelines, or dispute resolution becomes a full-time ops burden that scales with GMV in the worst way.
One thing that holds across categories: decide liability allocation before you launch, not in response to your first fraud case. Retroactively amending terms with active sellers is legally murky and surfaces the conflict at exactly the wrong moment.
What Stripe Connect Does Not Handle
Stripe Connect is infrastructure, not policy. It does not:
- Decide when funds should release
- Send dispute notifications to buyers and sellers in your own voice
- Maintain your order state machine
- Handle communications around holds or unexpected delays
- Automatically comply with local escrow regulations
On the regulatory point: true escrow — the kind governed by state law — requires a licensed escrow agent in several US states for specific transaction types. Stripe positions itself as a payment processor with flexible fund flow, not a licensed escrow provider. For most SMB marketplace categories (services, digital goods, physical products under common thresholds), this distinction does not matter operationally. For real estate or high-value financial instruments, it is a question for a lawyer, not an API.
The state machine, notification layer, and dispute interface are yours to build. This is where the real complexity of a marketplace build lives — the Stripe primitives are well-documented, but the business logic layered on top is specific to your category and hard to replicate with generic tools.
Dev Paragon has built Stripe Connect fund flows for marketplaces across services, rentals, and physical goods — including the state machines, admin dispute queues, and reserve logic described here. If you are designing your release conditions before launch, or trying to untangle a fund flow that grew organically without a deliberate structure, we are glad to think through it with you.
0 Comment