Marketplace Building
Overview
A multi-vendor marketplace lets independent sellers list products on your platform, collects payment from buyers, deducts your commission, and pays out the remainder to sellers. The key components are: seller onboarding with KYC verification, product listing management per seller, commission calculation, and automated payouts. For Shopify and WooCommerce merchants, purpose-built marketplace apps handle most of this — custom development is needed primarily for highly specific commission structures or white-label marketplace platforms.
When to Use This Skill
- When building a platform where third-party sellers list and sell their own products (not your inventory)
- When you need the platform to collect payment from buyers and distribute funds to sellers minus a commission
- When sellers need their own dashboard to manage listings, view orders, and track earnings
- When complying with KYC (Know Your Customer) requirements for seller identity verification
- When designing the commission structure (percentage, tiered, category-based) and payout schedule
Core Instructions
Step 1: Determine your platform and choose the right marketplace tool
| Platform |
Recommended Tool |
Why |
| Shopify |
Multi Vendor Marketplace by Webkul or BOLD Multi-Vendor |
Webkul's app adds seller accounts, product management, commission rules, and a seller dashboard to Shopify without replacing the storefront |
| WooCommerce |
Dokan Multi-Vendor (most popular, 60K+ installs) or WC Vendors |
Dokan is purpose-built for WooCommerce marketplaces with seller onboarding, commission management, payout requests, and a seller dashboard |
| BigCommerce |
Multi Vendor Marketplace by Webkul (BigCommerce version) |
Webkul has a BigCommerce version of their marketplace app |
| Custom / Headless |
Build seller accounts + Stripe Connect for KYC and payouts |
Stripe Connect handles KYC, bank account collection, and 1099-K tax forms — use it for any custom marketplace |
Step 2: Set up seller onboarding and KYC
KYC (Know Your Customer) is required to verify seller identity before you can legally send them payments. Using Stripe Connect for this is strongly recommended — building it yourself is expensive and legally complex.
Shopify — Multi Vendor Marketplace by Webkul
- Install Multi Vendor Marketplace by Webkul from the Shopify App Store
- Sellers register via a seller signup form (customizable URL, e.g.,
yourstore.com/seller/register)
- You approve seller applications manually in the Webkul admin — review the seller profile before approval
- Connect Webkul to Stripe Connect for payouts: go to Webkul → Settings → Payment → Stripe Connect and enter your Stripe credentials
- When you approve a seller, Webkul sends them an onboarding email with a link to connect their Stripe account (Stripe Express account — Stripe handles KYC and bank details)
- Seller is live once their Stripe Express account is verified (Stripe notifies you via webhook)
WooCommerce — Dokan Multi-Vendor
- Install Dokan Multi-Vendor Plugin from WordPress.org (free) or Dokan.com (pro)
- Enable seller registration: go to Dokan → Settings → General → Allow Registration
- Customize the seller registration form with required fields (business name, tax ID, bank info)
- For KYC: Dokan Pro integrates with Stripe Connect — go to Dokan → Settings → Withdrawal → Stripe Connect and enter your Stripe platform credentials
- Sellers connect their bank accounts via the Stripe Connect onboarding flow built into Dokan
- In Dokan → Vendors, approve or reject seller applications manually
Custom / Headless — Stripe Connect for KYC
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
// Create a Stripe Express account for a new seller and return the onboarding URL
async function onboardSeller(sellerId: string, sellerEmail: string): Promise<string> {
// Create the Stripe Express account
const account = await stripe.accounts.create({
type: 'express',
email: sellerEmail,
capabilities: {
transfers: { requested: true },
},
});
// Store the Stripe account ID on the seller record
await db.sellers.update(sellerId, { stripe_account_id: account.id });
// Generate the onboarding link (valid for 24 hours)
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: `${process.env.APP_URL}/seller/onboarding/refresh`,
return_url: `${process.env.APP_URL}/seller/onboarding/complete`,
type: 'account_onboarding',
});
return accountLink.url; // send this URL to the seller
}
// Webhook handler: activate seller when Stripe confirms KYC is complete
async function handleStripeAccountUpdated(account: Stripe.Account): Promise<void> {
const seller = await db.sellers.findByStripeAccountId(account.id);
if (!seller) return;
if (account.charges_enabled && account.payouts_enabled && seller.status !== 'active') {
await db.sellers.update(seller.id, { status: 'active' });
// Send welcome email to seller
}
}
Step 3: Set up product listings per seller
Shopify (Webkul)
- Approved sellers log in to their Seller Dashboard at
yourstore.com/seller/dashboard
- Sellers add products from their dashboard — products are submitted to you for approval before going live (configurable in Webkul settings)
- You control whether sellers can set their own prices or if all prices need your approval
- Product images, descriptions, and inventory are all managed by the seller from their dashboard
WooCommerce (Dokan)
- Sellers access their store dashboard at
yourstore.com/dashboard
- Sellers add products from Dokan → Products → Add New
- Enable "Product Review" in Dokan settings to require your approval before new products go live
- Sellers manage their own inventory counts, product variations, and prices
- In Dokan Pro, you can set commission rates at the product level, category level, or globally
Step 4: Configure commission rules and payouts
Shopify (Webkul)
- Go to Webkul → Commission to set commission rates:
- Global commission: e.g., 15% on all sales
- Seller-specific: override for specific sellers (e.g., 10% for VIP sellers)
- Category-specific: different rates by product category
- Commissions are deducted automatically from each order when paid
- Seller earnings are tracked in Webkul → Payments → Seller Transactions
- To pay out sellers: go to Webkul → Payments → Process Payout. Select sellers and click Process via Stripe Connect — funds transfer from your Stripe balance to the seller's connected account
WooCommerce (Dokan)
- Go to Dokan → Settings → Selling → Commission to set the global commission rate
- Override per-seller in Dokan → Vendors → [Seller] → Commission
- Sellers request withdrawals from their dashboard (Dokan → Withdraw Requests)
- You approve withdrawal requests in Dokan → Withdraw Requests → Pending
- For automated payouts via Stripe: Dokan Pro's Stripe Connect module automatically processes approved withdrawal requests
Custom / Headless — commission and payout logic
// Calculate commission and record seller earnings when an order is paid
async function recordSellerEarning(params: {
orderId: string;
sellerId: string;
grossAmountCents: number; // what buyer paid for this seller's items
commissionRate: number; // e.g., 0.15 for 15%
}): Promise<void> {
const commissionCents = Math.round(params.grossAmountCents * params.commissionRate);
const netAmountCents = params.grossAmountCents - commissionCents;
// Funds held until return window closes (e.g., 30 days)
const availableAt = new Date();
availableAt.setDate(availableAt.getDate() + 30);
await db.sellerEarnings.insert({
seller_id: params.sellerId,
order_id: params.orderId,
gross_amount_cents: params.grossAmountCents,
commission_cents: commissionCents,
net_amount_cents: netAmountCents,
status: 'held', // becomes 'available' after return window
available_at: availableAt,
});
}
// Transfer available earnings to seller's Stripe account
async function payoutSeller(sellerId: string): Promise<void> {
const seller = await db.sellers.findById(sellerId);
const availableEarnings = await db.sellerEarnings.findAll({
seller_id: sellerId,
status: 'available',
available_at: { lte: new Date() },
});
const totalCents = availableEarnings.reduce((s, e) => s + e.net_amount_cents, 0);
if (totalCents < 100) return; // minimum payout $1.00
// Transfer from your Stripe balance to seller's connected account
const transfer = await stripe.transfers.create({
amount: totalCents,
currency: 'usd',
destination: seller.stripe_account_id,
metadata: { seller_id: sellerId },
});
// Mark earnings as paid out
await db.sellerEarnings.updateMany(
availableEarnings.map(e => e.id),
{ status: 'paid_out' }
);
}
Step 5: Set up seller dashboards
Shopify (Webkul)
- Sellers access a Webkul-provided dashboard at
yourstore.com/seller/dashboard showing: orders, products, earnings summary, and payout history
- Customize the dashboard appearance (colors, logo) in Webkul → Settings → Dashboard
WooCommerce (Dokan)
- Dokan provides a full frontend dashboard at
yourstore.com/dashboard with: sales analytics, product management, withdrawal requests, and order management
- The dashboard is highly customizable via Dokan's template overrides
Best Practices
- Use Stripe Connect Express for all seller payouts — Express handles KYC, bank account verification, and IRS 1099-K reporting; building this yourself is expensive and legally risky
- Hold funds for the return window — don't release earnings to sellers until the buyer's return window closes; releasing early means the platform absorbs refund losses
- Record commission in the same transaction as order confirmation — never compute commission asynchronously from a queue that might fail; the earning record must be atomic with the order
- Send payout summaries to sellers by email — weekly earnings summaries with order-level detail build seller trust and reduce support contacts
- Block seller publishing until Stripe onboarding is complete — check
charges_enabled && payouts_enabled on the Stripe account before allowing a seller to publish listings
Common Pitfalls
| Problem |
Solution |
| Payout fails but earnings marked as paid |
In Stripe Connect, use the transfer.created webhook to confirm success before marking earnings as paid_out; never mark paid-out in the same call that initiates the transfer |
| Platform pays out before buyer payment clears |
Only trigger payout eligibility from the payment_intent.succeeded webhook, not from checkout session creation |
| Seller lists products before KYC is verified |
Check Stripe account status (charges_enabled && payouts_enabled) before allowing product publication; Webkul and Dokan do this automatically |
| Seller disputes commission deduction |
Store the commission rate and gross amount on every seller_earning record; show sellers their commission calculation history in the seller dashboard |
Related Skills
- @multi-channel-selling
- @vendor-management
- @b2b-commerce
- @order-management-system
1---2name: marketplace-building3description: Launch a multi-vendor marketplace with seller onboarding, commission rules, automated payouts via Stripe Connect, and vendor dashboards4---56# Marketplace Building78## Overview910A multi-vendor marketplace lets independent sellers list products on your platform, collects payment from buyers, deducts your commission, and pays out the remainder to sellers. The key components are: seller onboarding with KYC verification, product listing management per seller, commission calculation, and automated payouts. For Shopify and WooCommerce merchants, purpose-built marketplace apps handle most of this — custom development is needed primarily for highly specific commission structures or white-label marketplace platforms.1112## When to Use This Skill1314- When building a platform where third-party sellers list and sell their own products (not your inventory)15- When you need the platform to collect payment from buyers and distribute funds to sellers minus a commission16- When sellers need their own dashboard to manage listings, view orders, and track earnings17- When complying with KYC (Know Your Customer) requirements for seller identity verification18- When designing the commission structure (percentage, tiered, category-based) and payout schedule1920## Core Instructions2122### Step 1: Determine your platform and choose the right marketplace tool2324| Platform | Recommended Tool | Why |25|----------|-----------------|-----|26| **Shopify** | Multi Vendor Marketplace by Webkul or BOLD Multi-Vendor | Webkul's app adds seller accounts, product management, commission rules, and a seller dashboard to Shopify without replacing the storefront |27| **WooCommerce** | Dokan Multi-Vendor (most popular, 60K+ installs) or WC Vendors | Dokan is purpose-built for WooCommerce marketplaces with seller onboarding, commission management, payout requests, and a seller dashboard |28| **BigCommerce** | Multi Vendor Marketplace by Webkul (BigCommerce version) | Webkul has a BigCommerce version of their marketplace app |29| **Custom / Headless** | Build seller accounts + Stripe Connect for KYC and payouts | Stripe Connect handles KYC, bank account collection, and 1099-K tax forms — use it for any custom marketplace |3031### Step 2: Set up seller onboarding and KYC3233KYC (Know Your Customer) is required to verify seller identity before you can legally send them payments. Using Stripe Connect for this is strongly recommended — building it yourself is expensive and legally complex.3435#### Shopify — Multi Vendor Marketplace by Webkul36371. Install **Multi Vendor Marketplace** by Webkul from the Shopify App Store382. Sellers register via a seller signup form (customizable URL, e.g., `yourstore.com/seller/register`)393. You approve seller applications manually in the Webkul admin — review the seller profile before approval404. Connect Webkul to **Stripe Connect** for payouts: go to Webkul → Settings → Payment → Stripe Connect and enter your Stripe credentials415. When you approve a seller, Webkul sends them an onboarding email with a link to connect their Stripe account (Stripe Express account — Stripe handles KYC and bank details)426. Seller is live once their Stripe Express account is verified (Stripe notifies you via webhook)4344#### WooCommerce — Dokan Multi-Vendor45461. Install **Dokan Multi-Vendor Plugin** from WordPress.org (free) or Dokan.com (pro)472. Enable seller registration: go to **Dokan → Settings → General → Allow Registration**483. Customize the seller registration form with required fields (business name, tax ID, bank info)494. For KYC: Dokan Pro integrates with **Stripe Connect** — go to Dokan → Settings → Withdrawal → Stripe Connect and enter your Stripe platform credentials505. Sellers connect their bank accounts via the Stripe Connect onboarding flow built into Dokan516. In Dokan → Vendors, approve or reject seller applications manually5253#### Custom / Headless — Stripe Connect for KYC5455```typescript56import Stripe from 'stripe';57const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);5859// Create a Stripe Express account for a new seller and return the onboarding URL60async function onboardSeller(sellerId: string, sellerEmail: string): Promise<string> {61 // Create the Stripe Express account62 const account = await stripe.accounts.create({63 type: 'express',64 email: sellerEmail,65 capabilities: {66 transfers: { requested: true },67 },68 });6970 // Store the Stripe account ID on the seller record71 await db.sellers.update(sellerId, { stripe_account_id: account.id });7273 // Generate the onboarding link (valid for 24 hours)74 const accountLink = await stripe.accountLinks.create({75 account: account.id,76 refresh_url: `${process.env.APP_URL}/seller/onboarding/refresh`,77 return_url: `${process.env.APP_URL}/seller/onboarding/complete`,78 type: 'account_onboarding',79 });8081 return accountLink.url; // send this URL to the seller82}8384// Webhook handler: activate seller when Stripe confirms KYC is complete85async function handleStripeAccountUpdated(account: Stripe.Account): Promise<void> {86 const seller = await db.sellers.findByStripeAccountId(account.id);87 if (!seller) return;8889 if (account.charges_enabled && account.payouts_enabled && seller.status !== 'active') {90 await db.sellers.update(seller.id, { status: 'active' });91 // Send welcome email to seller92 }93}94```9596### Step 3: Set up product listings per seller9798#### Shopify (Webkul)991001. Approved sellers log in to their Seller Dashboard at `yourstore.com/seller/dashboard`1012. Sellers add products from their dashboard — products are submitted to you for approval before going live (configurable in Webkul settings)1023. You control whether sellers can set their own prices or if all prices need your approval1034. Product images, descriptions, and inventory are all managed by the seller from their dashboard104105#### WooCommerce (Dokan)1061071. Sellers access their store dashboard at `yourstore.com/dashboard`1082. Sellers add products from Dokan → Products → Add New1093. Enable "Product Review" in Dokan settings to require your approval before new products go live1104. Sellers manage their own inventory counts, product variations, and prices1115. In Dokan Pro, you can set commission rates at the product level, category level, or globally112113### Step 4: Configure commission rules and payouts114115#### Shopify (Webkul)1161171. Go to **Webkul → Commission** to set commission rates:118 - Global commission: e.g., 15% on all sales119 - Seller-specific: override for specific sellers (e.g., 10% for VIP sellers)120 - Category-specific: different rates by product category1212. Commissions are deducted automatically from each order when paid1223. Seller earnings are tracked in Webkul → Payments → Seller Transactions1234. To pay out sellers: go to Webkul → Payments → Process Payout. Select sellers and click Process via Stripe Connect — funds transfer from your Stripe balance to the seller's connected account124125#### WooCommerce (Dokan)1261271. Go to **Dokan → Settings → Selling → Commission** to set the global commission rate1282. Override per-seller in Dokan → Vendors → [Seller] → Commission1293. Sellers request withdrawals from their dashboard (Dokan → Withdraw Requests)1304. You approve withdrawal requests in Dokan → Withdraw Requests → Pending1315. For automated payouts via Stripe: Dokan Pro's Stripe Connect module automatically processes approved withdrawal requests132133#### Custom / Headless — commission and payout logic134135```typescript136// Calculate commission and record seller earnings when an order is paid137async function recordSellerEarning(params: {138 orderId: string;139 sellerId: string;140 grossAmountCents: number; // what buyer paid for this seller's items141 commissionRate: number; // e.g., 0.15 for 15%142}): Promise<void> {143 const commissionCents = Math.round(params.grossAmountCents * params.commissionRate);144 const netAmountCents = params.grossAmountCents - commissionCents;145146 // Funds held until return window closes (e.g., 30 days)147 const availableAt = new Date();148 availableAt.setDate(availableAt.getDate() + 30);149150 await db.sellerEarnings.insert({151 seller_id: params.sellerId,152 order_id: params.orderId,153 gross_amount_cents: params.grossAmountCents,154 commission_cents: commissionCents,155 net_amount_cents: netAmountCents,156 status: 'held', // becomes 'available' after return window157 available_at: availableAt,158 });159}160161// Transfer available earnings to seller's Stripe account162async function payoutSeller(sellerId: string): Promise<void> {163 const seller = await db.sellers.findById(sellerId);164 const availableEarnings = await db.sellerEarnings.findAll({165 seller_id: sellerId,166 status: 'available',167 available_at: { lte: new Date() },168 });169170 const totalCents = availableEarnings.reduce((s, e) => s + e.net_amount_cents, 0);171 if (totalCents < 100) return; // minimum payout $1.00172173 // Transfer from your Stripe balance to seller's connected account174 const transfer = await stripe.transfers.create({175 amount: totalCents,176 currency: 'usd',177 destination: seller.stripe_account_id,178 metadata: { seller_id: sellerId },179 });180181 // Mark earnings as paid out182 await db.sellerEarnings.updateMany(183 availableEarnings.map(e => e.id),184 { status: 'paid_out' }185 );186}187```188189### Step 5: Set up seller dashboards190191#### Shopify (Webkul)192193- Sellers access a Webkul-provided dashboard at `yourstore.com/seller/dashboard` showing: orders, products, earnings summary, and payout history194- Customize the dashboard appearance (colors, logo) in Webkul → Settings → Dashboard195196#### WooCommerce (Dokan)197198- Dokan provides a full frontend dashboard at `yourstore.com/dashboard` with: sales analytics, product management, withdrawal requests, and order management199- The dashboard is highly customizable via Dokan's template overrides200201## Best Practices202203- **Use Stripe Connect Express for all seller payouts** — Express handles KYC, bank account verification, and IRS 1099-K reporting; building this yourself is expensive and legally risky204- **Hold funds for the return window** — don't release earnings to sellers until the buyer's return window closes; releasing early means the platform absorbs refund losses205- **Record commission in the same transaction as order confirmation** — never compute commission asynchronously from a queue that might fail; the earning record must be atomic with the order206- **Send payout summaries to sellers by email** — weekly earnings summaries with order-level detail build seller trust and reduce support contacts207- **Block seller publishing until Stripe onboarding is complete** — check `charges_enabled && payouts_enabled` on the Stripe account before allowing a seller to publish listings208209## Common Pitfalls210211| Problem | Solution |212|---------|----------|213| Payout fails but earnings marked as paid | In Stripe Connect, use the `transfer.created` webhook to confirm success before marking earnings as `paid_out`; never mark paid-out in the same call that initiates the transfer |214| Platform pays out before buyer payment clears | Only trigger payout eligibility from the `payment_intent.succeeded` webhook, not from checkout session creation |215| Seller lists products before KYC is verified | Check Stripe account status (`charges_enabled && payouts_enabled`) before allowing product publication; Webkul and Dokan do this automatically |216| Seller disputes commission deduction | Store the commission rate and gross amount on every `seller_earning` record; show sellers their commission calculation history in the seller dashboard |217218## Related Skills219220- @multi-channel-selling221- @vendor-management222- @b2b-commerce223- @order-management-system