What this add-on actually does
On an ordinary multivendor setup, the vendor's share of a sale leaves your control the moment the card clears. The buyer has paid, the vendor has been paid, and the item has not moved. If it never gets posted, you are the one apologising.
This add-on puts a gap between those two events. The buyer's card is charged as normal, but the vendor's share is held — sent on only after they mark the order shipped and a protection window of your choosing has passed. Three things then happen without you watching:
- If the vendor never ships, the buyer is refunded in full and the held payout is cancelled.
- If you refund an order, anything still held is cancelled, and anything already paid out is reversed out of the vendor's Stripe account.
- If a buyer's bank raises a chargeback, payouts on that order freeze, and if you lose the dispute the vendor's transfer is clawed back.
Is this really escrow? An honest answer
Stripe's own documentation states that Connect does not offer escrow services, on the grounds that escrow has a very specific legal definition — money held by a licensed, neutral third party who releases it when conditions are met. Nothing built on Connect meets that definition, and neither does this add-on.
What this is, precisely: a delayed, conditional payout. The buyer's money is charged into your Stripe balance and the vendor's share is not transferred until the release conditions are met. Between those moments the funds are yours — Stripe sees them that way, your bank sees them that way, and your accountant should too.
Two things follow, and both are on you. Held money is not ring-fenced, so do not spend a balance that is mostly other people's sales waiting to release. And holding customer funds can carry obligations depending on where you trade — worth ten minutes with an accountant before launch, not after.
We use the word "escrow" because it is what marketplace owners search for and the behaviour they picture — the mechanism behind Vinted, Depop, eBay and OfferUp buyer protection, where the seller is paid once the buyer has had a fair chance to say something went wrong. That is genuinely useful. It is just not a legal escrow arrangement, and we would rather say so now than let you find out later.
Why a marketplace needs it
A marketplace has a trust problem a single-seller shop does not. Your buyer is not buying from you; they are buying from a stranger, on the strength of your website's reputation. When that stranger does not post the parcel, the buyer does not blame the stranger — they blame you, they charge back, and they tell people.
Holding the payout fixes the incentive at both ends. The vendor has a reason to post promptly, because the clock does not start until they do. The buyer has a window in which a problem can still be fixed with the money in reach.
Dokan Lite has no payout holding of its own — the vendor is paid however your payment stack pays them, normally straight away. On Dokan Pro, check what its vendor payment methods do before buying this; what owners find missing is not the split, it is the held window with automatic refund reversal and chargeback claw-back. Splitting a payment is easy. Getting money back out of a vendor's account three weeks later is the hard part. The comparison page covers the rest.
How it works, step by step
Follow one £35 order from checkout to payout, with the release window at its default of 7 business days.
- The buyer pays. Checkout runs through the WooCommerce Stripe Gateway exactly as before, and the £35 lands in your Stripe balance, tagged so the vendor's transfer can be tied back to this order later.
- The payout is recorded, not sent. On the transition to paid, BazaarKit works out each vendor's share — line items after discounts, plus tax, plus their postage, minus whatever commission Dokan reports — and writes it to the order as a held payout. No money moves, and each vendor in a basket gets their own held amount.
- It appears in Money held, with the status Waiting on tracking — the release timer starts when the seller marks it shipped.
- The vendor posts the item and marks it shipped from their order page in the Dokan dashboard — the only thing that starts the clock, and deliberately their own action. The protection window then runs seven business days from that moment, skipping weekends, and the status counts down: Releases in 6 days.
- The payout releases. A job runs hourly; on the first run after the window closes it sends a Stripe Transfer of the vendor's share to their connected account, funded by the buyer's original charge rather than your general balance. The order is marked complete once every vendor on it is paid.
- If anything goes wrong first, it does not happen. A refund cancels it, an open chargeback freezes it, and a vendor who has not finished connecting Stripe simply keeps waiting.
Only Stripe orders are held; one paid by bank transfer or on delivery passes through untouched.
What your vendors see
A banner at the top of the Dokan dashboard reads “Connect Stripe to get paid”, noting that buyers can order now but a connected account is needed before held payouts release. One click creates a Stripe Express account and sends them to Stripe's own onboarding for identity checks and bank details. Stripe holds all of it — you never see a bank account number, and no card data touches your site. Name and address are prefilled from their WooCommerce profile where it is complete, and if Stripe rejects the prefill the account is created without it, so a vendor is never blocked.
Once through, the banner becomes a quiet “Payouts active” line with a Manage payouts link into their Stripe Express dashboard. To put the same prompt elsewhere — a “Sell with us” page, say — the shortcode [bazaarkit_stripe_onboarding] renders that card on any page, showing logged-out visitors a sign-in prompt rather than a dead button.
On an order itself, a vendor sees one of three things — the part that saves you support tickets:
- Not yet shipped: a Mark as shipped button — “Starts the buyer-protection window. Your payout releases a few working days after this.”
- Shipped: “Marked as shipped. Your payout releases around 14 March.” That date uses the same window and weekday maths the payout job does, so what they are told and what happens cannot drift apart.
- Held: “Your £35.00 payout from this order is on hold”, then the actual reason — no payout account connected, or one that still needs finishing — a link to fix it, and “the money is safely held, not lost”. A generic “connect Stripe” nudge gets ignored; a named amount on a real order does not.
What buyers get
Nothing changes at checkout, which is intentional — nobody wants an extra step. What buyers get is behind the scenes, and worth saying on your own site somewhere: the seller is not paid until the item is on its way, a refund still works after the vendor has been paid, and if nothing ever ships they get their money back without asking.
That last one is deliberately generous. The buyer is made whole at the full amount they paid for that vendor's part of the order, postage included, while the claw-back on the other side only recovers the vendor's own share. If you would rather buyers raised problems during the window than waited it out, the Disputes & Resolution add-on gives them a structured way to do it, with the payout held while it is open.
Your settings, and what they change
Everything is on one screen: WordPress admin → BazaarKit → Escrow. The on/off switch sits with the other modules on BazaarKit → Add-ons.
| Setting | What it does | Default |
|---|---|---|
| Platform secret key (live) | Used for Connect work like creating vendor accounts and sending transfers. Leave blank to reuse the WooCommerce Stripe Gateway's key, though a dedicated platform key is recommended — one scoped to charges alone cannot perform platform-level actions. | Blank |
| Platform secret key (test) | The same, used whenever the add-on is running in test mode. | Blank |
| Test mode | Inherit from WooCommerce Stripe, Force test mode or Force live mode. Forcing test lets you rehearse the Connect flow on test keys while real buyer payments keep flowing live through the gateway. | Inherit |
| Release after (business days) | Working days between the vendor marking an order shipped and the payout going out. Weekends skipped, bank holidays not. Accepts 0–60; below 1 falls back to 7. | 7 |
| Warn vendor after (days) | Days after payment before an unshipped order earns the vendor a warning email counting down to the refund. | 5 |
| Auto-refund buyer after (days) | Days after payment before an unshipped order is refunded and cancelled. Set lower than the warning and it falls back to 7. | 7 |
| Connect signing secret (live & test) | Signing secret for the account.updated webhook. Without it that endpoint stays dormant and rejects everything. |
Blank |
| Chargeback signing secret (live & test) | Signing secret for the dispute webhook. Without it, chargebacks are not clawed back at all — this one is worth doing. | Blank |
| Marketplace business name | The name vendors see on their Stripe onboarding, written into the connected account's profile. | Your site name |
How long should the release window be?
Long enough for the item to arrive and for a disappointed buyer to say so; short enough that vendors do not feel they are funding you. Seven business days suits domestic post; 10 to 14 is more realistic for vendors shipping abroad (see International Shipping). Changing it affects payouts not yet released, so shortening it can release a batch on the next hourly run.
What you must set up in Stripe and WooCommerce
Four things, once.
- WooCommerce Stripe Gateway, working. Escrow rides on top of your existing Stripe checkout.
- Connect enabled on your Stripe account, and a platform key. Creating vendor accounts is a platform-level action, so paste a platform secret key into the Escrow settings. The one field not worth skipping.
- The Connect webhook. In Stripe, add an endpoint at
https://your-site/subscribed towp-json/ bazaarkit/ v1/ stripe/ connect-webhook account.updated, then paste its signing secret into the settings. It is how a vendor finishing their identity checks shows up straight away rather than at the next daily sync. - The chargeback webhook. A second endpoint at
https://your-site/subscribed towp-json/ bazaarkit/ v1/ stripe/ chargeback-webhook charge.dispute.createdandcharge.dispute.closed, with its own secret. Without it, a lost chargeback pulls money from your balance while the vendor keeps theirs.
Both URLs are printed on the settings screen with your domain filled in, so copy rather than type them. Each has its own secret, in separate live and test fields — which pair is used follows the Test mode setting. Every request is signature-verified, and an endpoint with no secret refuses everything.
Run one store currency. A vendor's transfer settles in the currency of the order, so if orders arrive in a currency your Stripe platform account does not settle in, Stripe may reject the transfer. BazaarKit logs a loud warning whenever it records a payout in a currency that differs from your WooCommerce base — resolve that before taking more orders.
A note on WP-Cron
The release job runs hourly and the buyer-protection job daily, both on WordPress's scheduler — which only fires when someone visits a page. If traffic is thin, point a real server cron at wp-cron.php so payouts do not drift late. Money held shows when the next run is due, and warns you if the job is not scheduled at all.
If your licence lapses
This is unusual enough to deserve its own section, because most paid plugins do the opposite. If your subscription lapses while money is still held, BazaarKit does not freeze that money. An expired card is not a reason to strand a vendor's earnings, so an unlicensed site stops taking new escrow — the only thing switched off — while every settlement path keeps running:
- Held payouts keep releasing on schedule.
- Refunds keep cancelling held money and reversing transfers, and chargebacks keep freezing and clawing back.
- Vendors can still connect Stripe — escrow held for an unconnected vendor is the money most at risk of being stranded.
- Vendors can still mark orders shipped, or the protection job would refund orders that were genuinely sent.
- The Escrow and Money held screens stay editable, so a Stripe key can still be rotated or a webhook secret re-pasted.
The Escrow screen says so rather than leaving you guessing: “This site has no active Escrow licence, so it is not taking any new escrow. Money it already holds is still being paid out, so these settings stay editable until the ledger is empty.”
Switching the module off on the Add-ons screen behaves identically — a toggle that reads like a feature switch should not quietly strand someone's earnings. Only deactivating the plugin stops settlement, and you should not do that with money still held. Once the ledger is empty the screen reverts to a locked preview: nothing to settle, nothing to break.
How to check it is working
Do this on staging with Stripe test keys, before you go anywhere near real money.
- In BazaarKit → Escrow, paste your Stripe test platform key, set Test mode to Force test mode, and set Release after to
1so you are not waiting a fortnight. Not0— that falls back to 7. - As a test vendor, connect a Stripe test account from the dashboard banner. Then, as a buyer, order from that vendor with a Stripe test card.
- Open BazaarKit → Money held: the order should be listed with the vendor's amount and the status Waiting on tracking. Confirm in Stripe that nothing has been sent.
- As the vendor, press Mark as shipped. The status changes to Releases in …, and after the window the hourly run clears the row, creates a transfer in Stripe and moves the order to Completed.
- For the unhappy path, place a second order, let it release, then refund it by line item. Stripe should show a reversal against that transfer.
Every step writes an order note, so an order's notes are a full audit trail of what the money did and when. If you would rather poke at a working marketplace than build one, the live demo has all of this set up.
Troubleshooting
Nothing ever appears in Money held
Check the order was paid with Stripe — anything else is deliberately ignored — and that it reached a paid status, since payouts are recorded on the transition to paid, not at order creation. On a multi-vendor basket the held payouts live on the parent order, not the sub-orders. And check the module is on in BazaarKit → Add-ons: an unlicensed or switched-off site settles old escrow but takes no new.
A payout is stuck and will not release
The Status column names the reason. Waiting on tracking means the vendor never pressed Mark as shipped, so the clock never started — by far the most common. Waiting on the seller means their Stripe onboarding is unfinished; the money is safe and goes out by itself once it is done. Frozen — dispute open means a chargeback is live. If the payout reads as due but nothing happens, check the note at the top of the screen: an unscheduled release job is fixed by deactivating and reactivating the add-on.
I refunded an order and the vendor's payout was not reversed
Refund by line item, not by typing an amount into the refund box. An amount-only refund carries nothing that says which vendor it belongs to. Rather than guess — or pay the vendor in full after you refunded the buyer — BazaarKit freezes the payout on that order and leaves a note saying so. Redo the refund against the specific items and postage. Refunds touching only platform fee lines are recognised as your own money and correctly leave the vendor alone.
A vendor says their Stripe onboarding link will not open
Stripe's onboarding links are single-use and expire within minutes, so a vendor returning to an old one gets nothing. Tell them to press Connect Stripe again: every click mints a brand new link, so a fresh attempt always works. The same goes for Manage payouts.
A webhook returns 400 when I test it from Stripe
No signing secret saved, or the wrong one — usually a live secret while Test mode is forced to test, or the Connect secret pasted into the chargeback field.
Frequently asked questions
Is this really escrow?
Not in the regulated, legal sense. Stripe's own documentation says Connect does not offer escrow services, because escrow has a very specific legal definition involving a licensed third party. This is delayed payout: the buyer's money sits in your Stripe balance until the protection window closes. Same mechanism as Vinted, Depop and eBay buyer protection — but you hold it, not a neutral third party.
Where does the money sit while it is held?
In your platform Stripe account. The buyer's card is charged into your balance, and a separate Stripe Transfer moves the vendor's share to their connected account later. Nothing is ring-fenced, so the funds are yours in the eyes of Stripe and your bank until released. Treat that as a responsibility, not a float.
When exactly does a vendor get paid?
The clock starts when the vendor marks the order shipped, not when the buyer pays. From there BazaarKit counts the business days set in Release after, which defaults to 7, and the hourly release job pays out on the first run after that. Weekends are skipped; bank holidays are not.
What happens if the vendor never ships?
A daily job watches every held payout not marked shipped. At 5 days the vendor is emailed a warning counting down; at 7 the buyer is refunded for that vendor's items and postage, that part of the order is cancelled and the held payout removed. Both thresholds are settings.
What if a buyer is refunded after the vendor was already paid?
BazaarKit reverses the Stripe Transfer. A refund first cancels anything still held for that vendor, which costs nothing because no money has moved; if that does not cover it, the remainder is reversed out of their connected account. Refund by line item, not a bare amount, so it can be matched to a vendor.
What happens on a chargeback weeks after payout?
The chargeback webhook freezes every payout on that order the moment the dispute opens. Lost, and BazaarKit cancels anything still held and reverses every transfer already released. Won, and the freeze lifts. The buyer's side is never touched — the bank has already moved that money.
Do vendors need their own Stripe account?
Yes. Each connects a Stripe Express account from a banner in their Dokan dashboard, and Stripe handles the identity checks and bank details — you store neither those nor card data. A vendor can sell before connecting; their money is held and releases once they finish.
What happens to held money if my licence lapses?
Nothing freezes. BazaarKit stops taking new escrow but keeps settling what it holds: payouts release, refunds reverse, chargebacks claw back, and the Escrow and Money held screens stay editable so you can fix a rotated Stripe key. Only deactivating the plugin stops settlement.
Does it work with Dokan Lite, or do I need Dokan Pro?
It works with Dokan Lite, which does not hold vendor payouts at all — that is the gap this fills. If you own Dokan Pro the two coexist; check its vendor payment methods first, because what owners find missing is the held window with automatic reversal and claw-back.
Does Dokan's commission still apply?
Yes. The amount held is the vendor's share after whatever commission Dokan reports for that order, recorded at the time of sale and never revised — so a refund reverses using the commission that actually applied. At Dokan's default 0% the vendor is held their full items and postage.
Where to go next
Stop paying vendors before the parcel leaves.
£5 / $5 a month, cancel anytime — and it settles whatever it holds even if you stop paying. Install the free BazaarKit core first, then switch it on.
See pricing Try the live demo