@mercurjs/docs 2.2.0-canary.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/content/blocks.mdx +209 -0
- package/content/learn/architecture.mdx +215 -0
- package/content/learn/attributes.mdx +89 -0
- package/content/learn/blocks.mdx +99 -0
- package/content/learn/commissions.mdx +175 -0
- package/content/learn/concepts.mdx +84 -0
- package/content/learn/installation.mdx +117 -0
- package/content/learn/introduction.mdx +71 -0
- package/content/learn/offers.mdx +78 -0
- package/content/learn/order-groups.mdx +114 -0
- package/content/learn/payouts.mdx +175 -0
- package/content/learn/product-requests.mdx +82 -0
- package/content/learn/products.mdx +79 -0
- package/content/learn/registry.mdx +155 -0
- package/content/learn/seller-members.mdx +62 -0
- package/content/learn/sellers.mdx +118 -0
- package/content/migration/from-1-x-to-2-0.mdx +152 -0
- package/content/migration/from-2-0-to-2-1.mdx +105 -0
- package/content/migration/overview.mdx +58 -0
- package/content/references/api/admin/commission-rates/batch-commission-rules.mdx +70 -0
- package/content/references/api/admin/commission-rates/create-commission-rate.mdx +95 -0
- package/content/references/api/admin/commission-rates/delete-commission-rate.mdx +40 -0
- package/content/references/api/admin/commission-rates/list-commission-rates.mdx +92 -0
- package/content/references/api/admin/commission-rates/retrieve-commission-rate.mdx +70 -0
- package/content/references/api/admin/commission-rates/update-commission-rate.mdx +84 -0
- package/content/references/api/admin/members/list-members.mdx +61 -0
- package/content/references/api/admin/offers/batch-create-offers.mdx +130 -0
- package/content/references/api/admin/offers/delete-offer.mdx +40 -0
- package/content/references/api/admin/offers/list-offers.mdx +106 -0
- package/content/references/api/admin/offers/retrieve-offer.mdx +82 -0
- package/content/references/api/admin/order-groups/list-order-groups.mdx +77 -0
- package/content/references/api/admin/order-groups/retrieve-order-group.mdx +56 -0
- package/content/references/api/admin/orders/get-order-commission-lines.mdx +65 -0
- package/content/references/api/admin/orders/get-order-order-group.mdx +56 -0
- package/content/references/api/admin/orders/list-orders.mdx +79 -0
- package/content/references/api/admin/payouts/list-payouts.mdx +75 -0
- package/content/references/api/admin/payouts/retrieve-payout.mdx +62 -0
- package/content/references/api/admin/product-attributes/create-attribute-value.mdx +76 -0
- package/content/references/api/admin/product-attributes/create-product-attribute.mdx +99 -0
- package/content/references/api/admin/product-attributes/delete-attribute-value.mdx +52 -0
- package/content/references/api/admin/product-attributes/delete-product-attribute.mdx +40 -0
- package/content/references/api/admin/product-attributes/list-product-attributes.mdx +91 -0
- package/content/references/api/admin/product-attributes/retrieve-product-attribute.mdx +81 -0
- package/content/references/api/admin/product-attributes/update-attribute-value.mdx +66 -0
- package/content/references/api/admin/product-attributes/update-product-attribute.mdx +76 -0
- package/content/references/api/admin/product-changes/cancel-product-change.mdx +68 -0
- package/content/references/api/admin/product-changes/confirm-product-change.mdx +47 -0
- package/content/references/api/admin/products/batch-product-attributes.mdx +96 -0
- package/content/references/api/admin/products/confirm-product.mdx +59 -0
- package/content/references/api/admin/products/create-product-variant.mdx +78 -0
- package/content/references/api/admin/products/create-product.mdx +169 -0
- package/content/references/api/admin/products/delete-product-variant.mdx +48 -0
- package/content/references/api/admin/products/delete-product.mdx +40 -0
- package/content/references/api/admin/products/list-product-variants.mdx +91 -0
- package/content/references/api/admin/products/list-products.mdx +109 -0
- package/content/references/api/admin/products/preview-product.mdx +78 -0
- package/content/references/api/admin/products/reject-product.mdx +59 -0
- package/content/references/api/admin/products/request-product-changes.mdx +59 -0
- package/content/references/api/admin/products/retrieve-product-variant.mdx +73 -0
- package/content/references/api/admin/products/retrieve-product.mdx +96 -0
- package/content/references/api/admin/products/set-product-sellers.mdx +47 -0
- package/content/references/api/admin/products/update-product-variant.mdx +89 -0
- package/content/references/api/admin/products/update-product.mdx +133 -0
- package/content/references/api/admin/sellers/add-seller-member.mdx +63 -0
- package/content/references/api/admin/sellers/approve-seller.mdx +54 -0
- package/content/references/api/admin/sellers/create-seller.mdx +100 -0
- package/content/references/api/admin/sellers/delete-member-invite.mdx +42 -0
- package/content/references/api/admin/sellers/delete-professional-details.mdx +52 -0
- package/content/references/api/admin/sellers/invite-seller-member.mdx +63 -0
- package/content/references/api/admin/sellers/list-member-invites.mdx +71 -0
- package/content/references/api/admin/sellers/list-seller-members.mdx +71 -0
- package/content/references/api/admin/sellers/list-seller-products.mdx +85 -0
- package/content/references/api/admin/sellers/list-sellers.mdx +96 -0
- package/content/references/api/admin/sellers/remove-seller-member.mdx +42 -0
- package/content/references/api/admin/sellers/resend-member-invite.mdx +55 -0
- package/content/references/api/admin/sellers/retrieve-seller.mdx +81 -0
- package/content/references/api/admin/sellers/suspend-seller.mdx +60 -0
- package/content/references/api/admin/sellers/terminate-seller.mdx +60 -0
- package/content/references/api/admin/sellers/unsuspend-seller.mdx +52 -0
- package/content/references/api/admin/sellers/unterminate-seller.mdx +52 -0
- package/content/references/api/admin/sellers/update-seller.mdx +83 -0
- package/content/references/api/admin/sellers/upsert-payment-details.mdx +88 -0
- package/content/references/api/admin/sellers/upsert-professional-details.mdx +78 -0
- package/content/references/api/admin/sellers/upsert-seller-address.mdx +91 -0
- package/content/references/api/admin.mdx +134 -0
- package/content/references/api/conventions.mdx +109 -0
- package/content/references/api/store/carts/add-line-item.mdx +115 -0
- package/content/references/api/store/carts/add-shipping-methods.mdx +84 -0
- package/content/references/api/store/carts/apply-promotions.mdx +83 -0
- package/content/references/api/store/carts/complete-cart.mdx +98 -0
- package/content/references/api/store/offers/list-offers.mdx +161 -0
- package/content/references/api/store/offers/retrieve-offer.mdx +112 -0
- package/content/references/api/store/order-groups/list-order-groups.mdx +105 -0
- package/content/references/api/store/order-groups/retrieve-order-group.mdx +78 -0
- package/content/references/api/store/product-attributes/list-product-attributes.mdx +134 -0
- package/content/references/api/store/product-attributes/retrieve-product-attribute.mdx +78 -0
- package/content/references/api/store/product-categories/list-product-categories.mdx +126 -0
- package/content/references/api/store/product-categories/retrieve-product-category.mdx +79 -0
- package/content/references/api/store/products/list-products.mdx +184 -0
- package/content/references/api/store/products/retrieve-product.mdx +107 -0
- package/content/references/api/store/search/search.mdx +136 -0
- package/content/references/api/store/sellers/list-sellers.mdx +105 -0
- package/content/references/api/store/sellers/retrieve-seller.mdx +62 -0
- package/content/references/api/store/shipping-options/list-shipping-options.mdx +74 -0
- package/content/references/api/store.mdx +67 -0
- package/content/references/api/vendor/members/accept-member-invite.mdx +65 -0
- package/content/references/api/vendor/members/retrieve-current-member.mdx +51 -0
- package/content/references/api/vendor/members/update-current-member.mdx +70 -0
- package/content/references/api/vendor/offers/batch-create-offers.mdx +123 -0
- package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +103 -0
- package/content/references/api/vendor/offers/create-offer.mdx +141 -0
- package/content/references/api/vendor/offers/delete-offer.mdx +51 -0
- package/content/references/api/vendor/offers/list-offers.mdx +125 -0
- package/content/references/api/vendor/offers/retrieve-offer.mdx +74 -0
- package/content/references/api/vendor/offers/update-offer.mdx +82 -0
- package/content/references/api/vendor/orders/cancel-fulfillment.mdx +63 -0
- package/content/references/api/vendor/orders/cancel-order.mdx +56 -0
- package/content/references/api/vendor/orders/complete-order.mdx +55 -0
- package/content/references/api/vendor/orders/create-fulfillment.mdx +76 -0
- package/content/references/api/vendor/orders/create-shipment.mdx +99 -0
- package/content/references/api/vendor/orders/get-order-commission-lines.mdx +66 -0
- package/content/references/api/vendor/orders/list-order-changes.mdx +75 -0
- package/content/references/api/vendor/orders/list-orders.mdx +103 -0
- package/content/references/api/vendor/orders/mark-fulfillment-delivered.mdx +62 -0
- package/content/references/api/vendor/orders/preview-order.mdx +65 -0
- package/content/references/api/vendor/orders/retrieve-order.mdx +84 -0
- package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +68 -0
- package/content/references/api/vendor/payout-accounts/create-payout-account.mdx +59 -0
- package/content/references/api/vendor/payout-accounts/retrieve-payout-account-by-id.mdx +60 -0
- package/content/references/api/vendor/payout-accounts/retrieve-payout-account.mdx +77 -0
- package/content/references/api/vendor/payouts/list-payouts.mdx +90 -0
- package/content/references/api/vendor/payouts/retrieve-payout.mdx +63 -0
- package/content/references/api/vendor/product-attributes/list-product-attributes.mdx +135 -0
- package/content/references/api/vendor/product-attributes/retrieve-product-attribute.mdx +71 -0
- package/content/references/api/vendor/product-variants/list-variants.mdx +136 -0
- package/content/references/api/vendor/products/batch-product-attributes.mdx +104 -0
- package/content/references/api/vendor/products/cancel-product-change.mdx +62 -0
- package/content/references/api/vendor/products/create-product-variant.mdx +92 -0
- package/content/references/api/vendor/products/create-product.mdx +197 -0
- package/content/references/api/vendor/products/delete-product-variant.mdx +68 -0
- package/content/references/api/vendor/products/delete-product.mdx +62 -0
- package/content/references/api/vendor/products/list-product-variants.mdx +114 -0
- package/content/references/api/vendor/products/list-products.mdx +163 -0
- package/content/references/api/vendor/products/preview-product.mdx +61 -0
- package/content/references/api/vendor/products/retrieve-product-variant.mdx +76 -0
- package/content/references/api/vendor/products/retrieve-product.mdx +69 -0
- package/content/references/api/vendor/products/update-product-variant.mdx +104 -0
- package/content/references/api/vendor/products/update-product.mdx +148 -0
- package/content/references/api/vendor/sellers/create-seller.mdx +150 -0
- package/content/references/api/vendor/sellers/delete-professional-details.mdx +54 -0
- package/content/references/api/vendor/sellers/invite-seller-member.mdx +67 -0
- package/content/references/api/vendor/sellers/list-member-invites.mdx +82 -0
- package/content/references/api/vendor/sellers/list-seller-members.mdx +80 -0
- package/content/references/api/vendor/sellers/list-sellers.mdx +71 -0
- package/content/references/api/vendor/sellers/remove-seller-member.mdx +48 -0
- package/content/references/api/vendor/sellers/retrieve-current-seller-member.mdx +59 -0
- package/content/references/api/vendor/sellers/retrieve-current-seller.mdx +69 -0
- package/content/references/api/vendor/sellers/select-seller.mdx +44 -0
- package/content/references/api/vendor/sellers/update-current-seller.mdx +108 -0
- package/content/references/api/vendor/sellers/update-member-role.mdx +51 -0
- package/content/references/api/vendor/sellers/upsert-payment-details.mdx +74 -0
- package/content/references/api/vendor/sellers/upsert-professional-details.mdx +70 -0
- package/content/references/api/vendor/sellers/upsert-seller-address.mdx +81 -0
- package/content/references/api/vendor.mdx +150 -0
- package/content/references/configuration.mdx +155 -0
- package/content/references/modules/commission.mdx +106 -0
- package/content/references/modules/custom-fields.mdx +45 -0
- package/content/references/modules/media.mdx +55 -0
- package/content/references/modules/offer.mdx +64 -0
- package/content/references/modules/payout.mdx +121 -0
- package/content/references/modules/product-attribute.mdx +111 -0
- package/content/references/modules/product-edit.mdx +80 -0
- package/content/references/modules/search.mdx +112 -0
- package/content/references/modules/seller.mdx +175 -0
- package/content/references/overview.mdx +70 -0
- package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +44 -0
- package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +36 -0
- package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +39 -0
- package/content/references/workflows/cart/update-cart-seller-promotions.mdx +42 -0
- package/content/references/workflows/commission/batch-commission-rules.mdx +45 -0
- package/content/references/workflows/commission/create-commission-rates.mdx +41 -0
- package/content/references/workflows/commission/delete-commission-rates.mdx +34 -0
- package/content/references/workflows/commission/refresh-order-commission-lines.mdx +30 -0
- package/content/references/workflows/commission/update-commission-rates.mdx +35 -0
- package/content/references/workflows/media/set-category-images.mdx +41 -0
- package/content/references/workflows/media/set-collection-images.mdx +41 -0
- package/content/references/workflows/member/accept-member-invite.mdx +33 -0
- package/content/references/workflows/member/add-seller-member.mdx +30 -0
- package/content/references/workflows/member/create-member-invites.mdx +34 -0
- package/content/references/workflows/member/delete-member-invite.mdx +24 -0
- package/content/references/workflows/member/remove-seller-member.mdx +28 -0
- package/content/references/workflows/member/resend-member-invite.mdx +28 -0
- package/content/references/workflows/member/update-member-role.mdx +28 -0
- package/content/references/workflows/member/update-member.mdx +35 -0
- package/content/references/workflows/offer/batch-offer-inventory-items.mdx +58 -0
- package/content/references/workflows/offer/create-offers.mdx +63 -0
- package/content/references/workflows/offer/delete-offers.mdx +35 -0
- package/content/references/workflows/offer/update-offers.mdx +51 -0
- package/content/references/workflows/order/cancel-order-fulfillment.mdx +34 -0
- package/content/references/workflows/order/confirm-claim-request.mdx +25 -0
- package/content/references/workflows/order/confirm-exchange-request.mdx +25 -0
- package/content/references/workflows/order/confirm-order-edit-request.mdx +25 -0
- package/content/references/workflows/order/confirm-return-receive.mdx +25 -0
- package/content/references/workflows/order/create-order-fulfillment.mdx +45 -0
- package/content/references/workflows/order-group/get-order-group-detail.mdx +29 -0
- package/content/references/workflows/order-group/get-order-groups-list.mdx +36 -0
- package/content/references/workflows/overview.mdx +72 -0
- package/content/references/workflows/payout/create-onboarding.mdx +36 -0
- package/content/references/workflows/payout/create-payout-account.mdx +33 -0
- package/content/references/workflows/payout/create-payout.mdx +30 -0
- package/content/references/workflows/payout/process-payout-for-webhook.mdx +32 -0
- package/content/references/workflows/product/confirm-products.mdx +46 -0
- package/content/references/workflows/product/create-products.mdx +63 -0
- package/content/references/workflows/product/link-sellers-to-product-category.mdx +40 -0
- package/content/references/workflows/product/link-sellers-to-product.mdx +40 -0
- package/content/references/workflows/product/reject-product.mdx +46 -0
- package/content/references/workflows/product/request-product-change.mdx +46 -0
- package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +49 -0
- package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +46 -0
- package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +43 -0
- package/content/references/workflows/product-attribute/create-product-attributes.mdx +56 -0
- package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +30 -0
- package/content/references/workflows/product-attribute/delete-product-attributes.mdx +30 -0
- package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +29 -0
- package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +44 -0
- package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +41 -0
- package/content/references/workflows/product-attribute/update-product-attributes.mdx +48 -0
- package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +43 -0
- package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +39 -0
- package/content/references/workflows/product-edit/cancel-product-change.mdx +49 -0
- package/content/references/workflows/product-edit/confirm-product-change.mdx +57 -0
- package/content/references/workflows/product-edit/create-product-change.mdx +72 -0
- package/content/references/workflows/product-edit/reject-product-change.mdx +54 -0
- package/content/references/workflows/product-edit/stage-product-change.mdx +75 -0
- package/content/references/workflows/seller/approve-seller.mdx +34 -0
- package/content/references/workflows/seller/create-seller-account.mdx +59 -0
- package/content/references/workflows/seller/create-seller-defaults.mdx +22 -0
- package/content/references/workflows/seller/create-sellers.mdx +65 -0
- package/content/references/workflows/seller/delete-seller-professional-details.mdx +37 -0
- package/content/references/workflows/seller/delete-sellers.mdx +24 -0
- package/content/references/workflows/seller/invite-seller.mdx +28 -0
- package/content/references/workflows/seller/suspend-seller.mdx +35 -0
- package/content/references/workflows/seller/terminate-seller.mdx +35 -0
- package/content/references/workflows/seller/unsuspend-seller.mdx +34 -0
- package/content/references/workflows/seller/unterminate-seller.mdx +34 -0
- package/content/references/workflows/seller/update-seller-address.mdx +55 -0
- package/content/references/workflows/seller/update-seller-payment-details.mdx +52 -0
- package/content/references/workflows/seller/update-seller-professional-details.mdx +48 -0
- package/content/references/workflows/seller/update-sellers.mdx +57 -0
- package/content/resources/ai/llms.mdx +74 -0
- package/content/resources/ai/mcp.mdx +152 -0
- package/content/resources/ai/overview.mdx +97 -0
- package/content/resources/customization/custom-fields.mdx +182 -0
- package/content/resources/customization/extend-a-workflow.mdx +39 -0
- package/content/resources/customization/extending-panels.mdx +309 -0
- package/content/resources/deployment/medusa-cloud.mdx +167 -0
- package/content/resources/integrations/notifications.mdx +39 -0
- package/content/resources/integrations/search.mdx +122 -0
- package/content/resources/integrations/stripe-connect.mdx +395 -0
- package/content/resources/tutorials/add-a-block.mdx +74 -0
- package/content/resources/tutorials/attributes-and-variant-axes.mdx +111 -0
- package/content/resources/tutorials/build-a-block.mdx +134 -0
- package/content/resources/tutorials/configure-commissions.mdx +127 -0
- package/content/resources/tutorials/custom-api-route.mdx +142 -0
- package/content/resources/tutorials/custom-panel-page.mdx +78 -0
- package/content/resources/tutorials/first-marketplace.mdx +45 -0
- package/content/resources/tutorials/handle-product-requests.mdx +80 -0
- package/content/resources/tutorials/import-export-products.mdx +96 -0
- package/content/resources/tutorials/master-products-and-offers.mdx +89 -0
- package/content/resources/tutorials/recompose-a-page.mdx +129 -0
- package/content/resources/tutorials/replace-panel-components.mdx +116 -0
- package/content/resources/tutorials/seller-payouts-stripe.mdx +89 -0
- package/content/telemetry.mdx +67 -0
- package/content/tools/api-client.mdx +155 -0
- package/content/tools/cli.mdx +196 -0
- package/content/tools/dashboard-sdk.mdx +35 -0
- package/content/user-guide/admin/overview.mdx +23 -0
- package/content/user-guide/admin/stores.mdx +193 -0
- package/content/user-guide/vendor/overview.mdx +23 -0
- package/content/user-guide/vendor/stores.mdx +209 -0
- package/llms.txt +307 -0
- package/package.json +33 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Payout"
|
|
3
|
+
description: "How seller payouts work in Mercur — accounts, onboarding, payment capture, and the transfer pipeline."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The payout module handles the financial side of a marketplace — onboarding sellers to a payment provider, capturing authorized payments, and transferring funds to sellers after fulfillment.
|
|
7
|
+
|
|
8
|
+
## Payout account
|
|
9
|
+
|
|
10
|
+
Every seller that wants to receive funds needs a **PayoutAccount**. This account links a seller to an external payment provider (e.g. Stripe Connect).
|
|
11
|
+
|
|
12
|
+
### Account lifecycle
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
PENDING → ACTIVE
|
|
16
|
+
↓
|
|
17
|
+
RESTRICTED → ACTIVE (or REJECTED)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Status | Description |
|
|
21
|
+
|--------|-------------|
|
|
22
|
+
| `PENDING` | Account created, awaiting provider onboarding |
|
|
23
|
+
| `ACTIVE` | Fully onboarded, can receive payouts |
|
|
24
|
+
| `RESTRICTED` | Provider has flagged the account (e.g. missing KYC) |
|
|
25
|
+
| `REJECTED` | Provider rejected the account |
|
|
26
|
+
|
|
27
|
+
### Onboarding
|
|
28
|
+
|
|
29
|
+
When a payout account is created, an **Onboarding** record is attached to it. This stores provider-specific data needed for identity verification or account setup (e.g. Stripe Connect onboarding links).
|
|
30
|
+
|
|
31
|
+
## The payout pipeline
|
|
32
|
+
|
|
33
|
+
The payout flow is fully automated through two scheduled jobs and event-driven subscribers. No manual intervention is needed after configuration.
|
|
34
|
+
|
|
35
|
+
### 1. Capture check (every 15 minutes)
|
|
36
|
+
|
|
37
|
+
A scheduled job scans for orders that are ready for payment capture. For each order, it checks:
|
|
38
|
+
|
|
39
|
+
- Payment is in `authorized` status
|
|
40
|
+
- Seller has an `ACTIVE` payout account
|
|
41
|
+
- Order meets the required fulfillment status (configurable, default: `fulfilled`)
|
|
42
|
+
- No payout has been created yet
|
|
43
|
+
|
|
44
|
+
When the capture deadline approaches (authorization window minus safety buffer), the job emits an `order.capture_requested` event. If the authorization has already expired, it emits `order.authorization_expired` instead.
|
|
45
|
+
|
|
46
|
+
### 2. Payment capture (event-driven)
|
|
47
|
+
|
|
48
|
+
A subscriber listens for `order.capture_requested` events and runs the Medusa `capturePaymentWorkflow` to capture the authorized payment. On success, the order is marked as captured. On failure, the order is flagged so it won't be retried.
|
|
49
|
+
|
|
50
|
+
### 3. Daily payouts (once per day)
|
|
51
|
+
|
|
52
|
+
A daily scheduled job (1 AM UTC) scans for captured orders that haven't been paid out yet. For each eligible order, it emits a `payout.requested` event.
|
|
53
|
+
|
|
54
|
+
An order qualifies for payout when:
|
|
55
|
+
- Payment has been captured (`metadata.captured = true`)
|
|
56
|
+
- No existing payout transfer
|
|
57
|
+
- Seller has an `ACTIVE` payout account
|
|
58
|
+
|
|
59
|
+
### 4. Payout transfer (event-driven)
|
|
60
|
+
|
|
61
|
+
A subscriber listens for `payout.requested` events and runs the `createPayoutWorkflow`:
|
|
62
|
+
|
|
63
|
+
1. **Fetch order** — Loads the order with its seller, payout account, and commission lines
|
|
64
|
+
2. **Calculate payout amount** — Subtracts commission from the order total:
|
|
65
|
+
```
|
|
66
|
+
payout_amount = order.total - total_commission
|
|
67
|
+
```
|
|
68
|
+
3. **Create payout** — Calls the payment provider to initiate the transfer and creates a `Payout` record
|
|
69
|
+
4. **Link payout** — Associates the payout with the seller
|
|
70
|
+
|
|
71
|
+
### Payout statuses
|
|
72
|
+
|
|
73
|
+
| Status | Description |
|
|
74
|
+
|--------|-------------|
|
|
75
|
+
| `PENDING` | Payout created, transfer initiated |
|
|
76
|
+
| `PROCESSING` | Provider is processing the transfer |
|
|
77
|
+
| `PAID` | Funds successfully transferred |
|
|
78
|
+
| `FAILED` | Transfer failed |
|
|
79
|
+
| `CANCELED` | Transfer was canceled |
|
|
80
|
+
|
|
81
|
+
Payout statuses are updated via webhook events from the payment provider.
|
|
82
|
+
|
|
83
|
+
### Webhook handling
|
|
84
|
+
|
|
85
|
+
A subscriber listens for `payout.webhook_received` events and delegates to the `processPayoutForWebhookWorkflow`. The provider parses the raw webhook payload and returns an action:
|
|
86
|
+
|
|
87
|
+
**Account events:**
|
|
88
|
+
- `account.activated` → Status set to `ACTIVE`
|
|
89
|
+
- `account.restricted` → Status set to `RESTRICTED`
|
|
90
|
+
- `account.rejected` → Status set to `REJECTED`
|
|
91
|
+
|
|
92
|
+
**Payout events:**
|
|
93
|
+
- `payout.processing` → Status set to `PROCESSING`
|
|
94
|
+
- `payout.paid` → Status set to `PAID`
|
|
95
|
+
- `payout.failed` → Status set to `FAILED`
|
|
96
|
+
- `payout.canceled` → Status set to `CANCELED`
|
|
97
|
+
|
|
98
|
+
## Configuration
|
|
99
|
+
|
|
100
|
+
The payout module accepts the following options in `medusa-config.ts`:
|
|
101
|
+
|
|
102
|
+
| Option | Default | Description |
|
|
103
|
+
|--------|---------|-------------|
|
|
104
|
+
| `disabled` | `false` | Disables both scheduled jobs |
|
|
105
|
+
| `authorizationWindowMs` | 7 days | How long a payment authorization is valid |
|
|
106
|
+
| `sellerActionWindowMs` | 72 hours | Time for seller to fulfill the order |
|
|
107
|
+
| `captureSafetyBufferMs` | 24 hours | Safety margin before authorization expiry to trigger capture |
|
|
108
|
+
| `requiredFulfillmentStatus` | `"fulfilled"` | Minimum fulfillment status before capture is allowed |
|
|
109
|
+
|
|
110
|
+
## Data model overview
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
PayoutAccount
|
|
114
|
+
├── Onboarding (one-to-one)
|
|
115
|
+
└── Payout (one-to-many, per-order transfers)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Configuration example
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// medusa-config.ts
|
|
122
|
+
{
|
|
123
|
+
resolve: "./modules/payout",
|
|
124
|
+
options: {
|
|
125
|
+
// How long payment authorizations are valid
|
|
126
|
+
authorizationWindowMs: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
127
|
+
|
|
128
|
+
// Time for seller to fulfill before capture
|
|
129
|
+
sellerActionWindowMs: 72 * 60 * 60 * 1000, // 72 hours
|
|
130
|
+
|
|
131
|
+
// Safety margin before authorization expiry
|
|
132
|
+
captureSafetyBufferMs: 24 * 60 * 60 * 1000, // 24 hours
|
|
133
|
+
|
|
134
|
+
// Minimum fulfillment status before capture
|
|
135
|
+
requiredFulfillmentStatus: "fulfilled",
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API examples
|
|
141
|
+
|
|
142
|
+
### Get seller's payout account (Vendor API)
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
curl http://localhost:9000/vendor/payout-accounts/<account-id> \
|
|
146
|
+
-H "Authorization: Bearer <seller-token>"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Create payout onboarding (Vendor API)
|
|
150
|
+
|
|
151
|
+
Initiates provider onboarding (e.g. Stripe Connect account setup). The `data` and `context` fields are passed to the payout provider:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
curl -X POST http://localhost:9000/vendor/payout-accounts/<account-id>/onboarding \
|
|
155
|
+
-H "Authorization: Bearer <seller-token>" \
|
|
156
|
+
-H "Content-Type: application/json" \
|
|
157
|
+
-d '{
|
|
158
|
+
"context": {
|
|
159
|
+
"return_url": "https://my-store.com/settings/payouts"
|
|
160
|
+
}
|
|
161
|
+
}'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### List payouts (Admin API)
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
curl http://localhost:9000/admin/payouts \
|
|
168
|
+
-H "Authorization: Bearer <admin-token>"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Provider abstraction
|
|
172
|
+
|
|
173
|
+
The payout module is **provider-agnostic**. A `PayoutProviderService` acts as a bridge to the external payment processor. It delegates all external operations — creating accounts, processing payouts, parsing webhooks — to a pluggable provider implementation.
|
|
174
|
+
|
|
175
|
+
The module expects exactly one payout provider to be registered. Provider-specific data is stored in the `data` JSON fields on accounts, payouts, and onboarding records.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Product Requests & Approvals"
|
|
3
|
+
description: "How vendor product submissions and edits are reviewed — the ProductChange pipeline that keeps a shared catalog under operator control."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Because the catalog is [shared](/rc/learn/products), vendors don't mutate products directly. New products and edits flow through a review pipeline built on **product changes** — structured requests the operator can confirm, decline, or send back for revision. The same records double as the product's audit trail.
|
|
7
|
+
|
|
8
|
+
There are two flows:
|
|
9
|
+
|
|
10
|
+
## 1. New-product approval
|
|
11
|
+
|
|
12
|
+
A vendor-created product enters the catalog with status `proposed` and is visible only to its creator. The operator reviews it from the Admin Panel:
|
|
13
|
+
|
|
14
|
+
- **Confirm** — the product is published into the shared catalog.
|
|
15
|
+
- **Reject** — the product is marked `rejected` and stays out of the catalog.
|
|
16
|
+
- **Request changes** — the submission is sent back to the vendor with a note for revision.
|
|
17
|
+
|
|
18
|
+
## 2. Edit change-requests
|
|
19
|
+
|
|
20
|
+
Edits to existing products — detail updates, variant additions/updates/removals, attribute changes — are captured as a **ProductChange**: a reviewable bundle of one or more ordered actions.
|
|
21
|
+
|
|
22
|
+
### ProductChange
|
|
23
|
+
|
|
24
|
+
| Field | Description |
|
|
25
|
+
|-------|-------------|
|
|
26
|
+
| `product_id` | The product the change targets |
|
|
27
|
+
| `status` | `pending` → `confirmed` / `declined` / `canceled` |
|
|
28
|
+
| `created_by` | Who requested the change |
|
|
29
|
+
| `confirmed_by` / `confirmed_at` | Review outcome audit fields (same pattern for declined/canceled) |
|
|
30
|
+
| `declined_reason` | Why a change was declined |
|
|
31
|
+
| `requires_action_by` / `requires_action_reason` | Set when the operator asks the vendor to revise |
|
|
32
|
+
| `internal_note` / `external_note` | Operator-only vs vendor-visible notes |
|
|
33
|
+
|
|
34
|
+
### ProductChangeAction
|
|
35
|
+
|
|
36
|
+
Each change groups ordered **actions** — the atomic operations applied to the live product when the change is confirmed:
|
|
37
|
+
|
|
38
|
+
| Action | Effect |
|
|
39
|
+
|--------|--------|
|
|
40
|
+
| `UPDATE` | Update product details |
|
|
41
|
+
| `VARIANT_ADD` / `VARIANT_UPDATE` / `VARIANT_REMOVE` | Variant operations |
|
|
42
|
+
| `ATTRIBUTE_ADD` / `ATTRIBUTE_UPDATE` / `ATTRIBUTE_REMOVE` | Attribute operations |
|
|
43
|
+
| `STATUS_CHANGE` | Status transitions (publish, reject) |
|
|
44
|
+
| `PRODUCT_ADD` / `PRODUCT_DELETE` | Creation and deletion markers |
|
|
45
|
+
|
|
46
|
+
Each action carries its payload in a `details` JSON field and an `applied` flag. Actions are applied in order on confirmation — nothing touches the live product while the change is `pending`.
|
|
47
|
+
|
|
48
|
+
## Lifecycle
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
┌────────────> confirmed ── actions applied to product
|
|
52
|
+
│
|
|
53
|
+
pending ─────┼────────────> declined ── with a reason
|
|
54
|
+
│
|
|
55
|
+
└────────────> canceled ── withdrawn by the requester
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The operator can also flag a pending change as **requires action**, handing it back to the vendor with a reason before a final decision.
|
|
59
|
+
|
|
60
|
+
Some low-risk edits are **auto-confirmed** — they still create a change record for the audit trail, but apply immediately without waiting for review.
|
|
61
|
+
|
|
62
|
+
## Audit trail
|
|
63
|
+
|
|
64
|
+
Confirmed changes are never deleted. The product's change history answers "who changed what, when, and who approved it" — including the original creation (`PRODUCT_ADD`), which is also what scopes a vendor's list to their own unpublished submissions.
|
|
65
|
+
|
|
66
|
+
## Where it appears
|
|
67
|
+
|
|
68
|
+
| Surface | Capability |
|
|
69
|
+
|---------|-----------|
|
|
70
|
+
| Admin Panel | Review queue on the product detail — confirm, reject, or request changes on submissions and pending edits |
|
|
71
|
+
| Vendor Portal | Shows the seller's own pending edits and revision requests on their product pages |
|
|
72
|
+
|
|
73
|
+
## Next steps
|
|
74
|
+
|
|
75
|
+
<CardGroup cols={2}>
|
|
76
|
+
<Card title="Products" href="/rc/learn/products">
|
|
77
|
+
The master-catalog model this pipeline protects.
|
|
78
|
+
</Card>
|
|
79
|
+
<Card title="Product Attributes" href="/rc/learn/attributes">
|
|
80
|
+
Attribute edits that flow through this pipeline.
|
|
81
|
+
</Card>
|
|
82
|
+
</CardGroup>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Products"
|
|
3
|
+
description: "Mercur products are master products — a single shared catalog for the whole marketplace, with selling eligibility instead of ownership."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Products in Mercur are **master products**: a single shared catalog of product records that the whole marketplace draws from. A product is **not** owned by the seller who created it — creating a product adds a candidate to the shared catalog, and sellers sell against that catalog through [offers](/rc/learn/offers).
|
|
7
|
+
|
|
8
|
+
This is the model used by large marketplaces: one canonical product record ("iPhone 15 Pro, 256 GB, Black"), many sellers listing against it.
|
|
9
|
+
|
|
10
|
+
## No product ownership
|
|
11
|
+
|
|
12
|
+
There is no owner column on a product. What looks like ownership in other platforms is split into three independent mechanisms:
|
|
13
|
+
|
|
14
|
+
| Mechanism | What it controls | What it does *not* control |
|
|
15
|
+
|-----------|-----------------|----------------------------|
|
|
16
|
+
| Selling eligibility (`product_seller` link) | Which sellers may sell the product and see it while restricted | Who can edit the product |
|
|
17
|
+
| Creator attribution | Which unpublished products appear in a seller's own list | Any rights over the product after publication |
|
|
18
|
+
| Status lifecycle | Who can see the product at all | Which seller it "belongs" to |
|
|
19
|
+
|
|
20
|
+
### Selling eligibility
|
|
21
|
+
|
|
22
|
+
The `product_seller` link is an **allowlist**, analogous to Medusa's `product_sales_channel` link:
|
|
23
|
+
|
|
24
|
+
- **Restricted** — a product assigned to one or more sellers is visible and sellable only for those sellers.
|
|
25
|
+
- **Unrestricted** — a product with no seller assignments is available to every seller on the marketplace (subject to its status).
|
|
26
|
+
|
|
27
|
+
Assignments are managed by the operator; creating a product does not assign it to the creator.
|
|
28
|
+
|
|
29
|
+
### Creator attribution
|
|
30
|
+
|
|
31
|
+
When a product is created, the platform records who created it as part of the product's [change history](/rc/learn/product-requests). This attribution has exactly one purpose: scoping vendor lists so a seller sees their own not-yet-published submissions without seeing other sellers' pending work.
|
|
32
|
+
|
|
33
|
+
## Status lifecycle
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
DRAFT ──> PROPOSED ──> PUBLISHED
|
|
37
|
+
│
|
|
38
|
+
└──────> REJECTED
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Status | Meaning |
|
|
42
|
+
|--------|---------|
|
|
43
|
+
| `draft` | Work in progress, not submitted |
|
|
44
|
+
| `proposed` | Submitted for review — visible only to its creator until published |
|
|
45
|
+
| `published` | Live in the shared catalog |
|
|
46
|
+
| `rejected` | Declined by the operator |
|
|
47
|
+
|
|
48
|
+
Vendor-created products default to **`proposed`**. The operator reviews the submission and publishes or rejects it — see [Product Requests & Approvals](/rc/learn/product-requests).
|
|
49
|
+
|
|
50
|
+
## Visibility rules
|
|
51
|
+
|
|
52
|
+
| Surface | What is visible |
|
|
53
|
+
|---------|----------------|
|
|
54
|
+
| Vendor | Products the seller created (any status) plus published products not restricted to other sellers |
|
|
55
|
+
| Admin | Every product, regardless of status or eligibility |
|
|
56
|
+
| Store | Published products of visible sellers |
|
|
57
|
+
|
|
58
|
+
The vendor rule in practice: a seller's product list is their own submissions **or** the shared published catalog, minus products allowlisted exclusively to other sellers.
|
|
59
|
+
|
|
60
|
+
## Editing shared products
|
|
61
|
+
|
|
62
|
+
Because the catalog is shared, edits are collaborative: **any seller may request a change to any product** — updating details, adding or removing variants, changing attributes. Edits flow through the [change-request pipeline](/rc/learn/product-requests) rather than mutating the product directly, so the operator stays in control of the shared record.
|
|
63
|
+
|
|
64
|
+
Eligibility restrictions limit who may *sell* a product; they do not limit who may *propose changes* to it.
|
|
65
|
+
|
|
66
|
+
## What sellers actually sell
|
|
67
|
+
|
|
68
|
+
A master product defines *what the item is*. It carries no seller price and no seller stock. To sell it, a seller creates an **offer** — their own SKU, price, inventory, and shipping profile bound to the product. This separation is what allows many sellers to compete on the same catalog entry.
|
|
69
|
+
|
|
70
|
+
## Next steps
|
|
71
|
+
|
|
72
|
+
<CardGroup cols={2}>
|
|
73
|
+
<Card title="Offers" href="/rc/learn/offers">
|
|
74
|
+
How sellers list, price, and stock products from the shared catalog.
|
|
75
|
+
</Card>
|
|
76
|
+
<Card title="Product Requests & Approvals" href="/rc/learn/product-requests">
|
|
77
|
+
How new products and edits are reviewed by the operator.
|
|
78
|
+
</Card>
|
|
79
|
+
</CardGroup>
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Registry"
|
|
3
|
+
description: "Create, build, and host your own block registry."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A registry is a collection of blocks that can be installed into any Mercur project using the CLI. The official Mercur registry (`@mercurjs`) provides all the built-in marketplace blocks. You can also create and host your own.
|
|
7
|
+
|
|
8
|
+
## How it works
|
|
9
|
+
|
|
10
|
+
A registry is a set of JSON files — one per block — served over HTTP. When you run `bunx @mercurjs/cli@rc add`, the CLI fetches the block's JSON, resolves its dependencies, and copies the source files into your project.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
registry/
|
|
14
|
+
├── registry.json # Registry definition with all blocks
|
|
15
|
+
├── src/
|
|
16
|
+
│ └── my-block/ # Block source files
|
|
17
|
+
│ ├── modules/
|
|
18
|
+
│ ├── workflows/
|
|
19
|
+
│ └── api/
|
|
20
|
+
└── r/ # Built output (generated)
|
|
21
|
+
├── registry.json
|
|
22
|
+
└── my-block.json # Block JSON with embedded file contents
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## registry.json
|
|
26
|
+
|
|
27
|
+
The `registry.json` file defines your registry and all its blocks:
|
|
28
|
+
|
|
29
|
+
```json registry.json
|
|
30
|
+
{
|
|
31
|
+
"$schema": "https://registry.mercurjs.com/registry.json",
|
|
32
|
+
"name": "@my-org",
|
|
33
|
+
"homepage": "https://my-org.com",
|
|
34
|
+
"items": [
|
|
35
|
+
{
|
|
36
|
+
"name": "reviews",
|
|
37
|
+
"description": "Product and seller reviews with ratings.",
|
|
38
|
+
"dependencies": [],
|
|
39
|
+
"registryDependencies": [],
|
|
40
|
+
"docs": "## Configuration\n\nAdd the review module to your `medusa-config.ts`...",
|
|
41
|
+
"files": [
|
|
42
|
+
{
|
|
43
|
+
"path": "reviews/modules/reviews/index.ts",
|
|
44
|
+
"type": "registry:module"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"path": "reviews/workflows/review/workflows/create-review.ts",
|
|
48
|
+
"type": "registry:workflow"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "reviews/api/store/reviews/route.ts",
|
|
52
|
+
"type": "registry:api"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"categories": ["module", "workflow", "api"]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Block properties
|
|
62
|
+
|
|
63
|
+
| Property | Description |
|
|
64
|
+
| ---------------------- | -------------------------------------------------------------- |
|
|
65
|
+
| `name` | Block identifier used in `bunx @mercurjs/cli@rc add` |
|
|
66
|
+
| `description` | Short description shown in search results |
|
|
67
|
+
| `dependencies` | NPM packages to install |
|
|
68
|
+
| `registryDependencies` | Other blocks this block depends on (e.g. `@mercurjs/wishlist`) |
|
|
69
|
+
| `docs` | Markdown shown to the user after installation |
|
|
70
|
+
| `files` | List of source files with their paths and types |
|
|
71
|
+
| `categories` | Tags for search and filtering |
|
|
72
|
+
|
|
73
|
+
### File types
|
|
74
|
+
|
|
75
|
+
Each file in a block has a `type` that determines where it gets placed in the target project:
|
|
76
|
+
|
|
77
|
+
| Type | Target alias |
|
|
78
|
+
| ------------------- | ------------ |
|
|
79
|
+
| `registry:module` | `modules` |
|
|
80
|
+
| `registry:workflow` | `workflows` |
|
|
81
|
+
| `registry:api` | `api` |
|
|
82
|
+
| `registry:link` | `links` |
|
|
83
|
+
| `registry:vendor` | `vendor` |
|
|
84
|
+
| `registry:admin` | `admin` |
|
|
85
|
+
| `registry:lib` | `lib` |
|
|
86
|
+
|
|
87
|
+
These map to the aliases defined in the consumer's `blocks.json`.
|
|
88
|
+
|
|
89
|
+
## Building
|
|
90
|
+
|
|
91
|
+
Build your registry into distributable JSON files:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
bunx @mercurjs/cli@rc build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This reads `registry.json`, resolves all imports for each block, embeds the file contents, and outputs one JSON file per block to the `r/` directory.
|
|
98
|
+
|
|
99
|
+
| Option | Description |
|
|
100
|
+
| --------------------- | --------------------------------- |
|
|
101
|
+
| `-o, --output <path>` | Output directory (default: `./r`) |
|
|
102
|
+
| `-v, --verbose` | Show detailed output |
|
|
103
|
+
|
|
104
|
+
The build step also automatically resolves NPM dependencies from your source imports — you don't need to list every transitive dependency manually.
|
|
105
|
+
|
|
106
|
+
## Hosting
|
|
107
|
+
|
|
108
|
+
Serve the built `r/` directory over HTTP. Any static hosting works — GitHub Pages, Vercel, Netlify, S3, or your own server. The only requirement is that `{name}.json` files are accessible at a public URL.
|
|
109
|
+
|
|
110
|
+
## Using custom registries
|
|
111
|
+
|
|
112
|
+
Add your registry to `blocks.json` in any Mercur project:
|
|
113
|
+
|
|
114
|
+
```json blocks.json
|
|
115
|
+
{
|
|
116
|
+
"registries": {
|
|
117
|
+
"@my-org": "https://my-registry.com/r/{name}.json"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use `{name}` as a placeholder for block names. Then install blocks from it:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
bunx @mercurjs/cli@rc add @my-org/reviews
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Authentication
|
|
129
|
+
|
|
130
|
+
For private registries, you can use headers with environment variables:
|
|
131
|
+
|
|
132
|
+
```json blocks.json
|
|
133
|
+
{
|
|
134
|
+
"registries": {
|
|
135
|
+
"@my-org": {
|
|
136
|
+
"url": "https://api.my-org.com/r/{name}.json",
|
|
137
|
+
"headers": {
|
|
138
|
+
"Authorization": "Bearer ${REGISTRY_TOKEN}"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Dependencies between blocks
|
|
146
|
+
|
|
147
|
+
Blocks can depend on other blocks using `registryDependencies`. When a user installs your block, the CLI automatically resolves and installs all dependencies in the correct order.
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"name": "order-tracking",
|
|
152
|
+
"registryDependencies": ["@mercurjs/wishlist"],
|
|
153
|
+
"files": [...]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Seller Members"
|
|
3
|
+
description: "Multi-user seller accounts — member data, team management, store switching, and access rules."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A **seller member** represents a user who has access to a seller account. Mercur supports **multi-user seller accounts** — multiple people can manage the same store — and **multi-seller users** — a single person can belong to more than one store. This page covers how members relate to sellers, how access is structured, and the rules governing team management.
|
|
7
|
+
|
|
8
|
+
## Concept
|
|
9
|
+
|
|
10
|
+
The relationship between users and sellers is **many-to-many**. A seller account can have several members (e.g. an owner, a warehouse manager, and a support agent), and a single user can be a member of multiple seller accounts (e.g. a consultant managing stores for different brands).
|
|
11
|
+
|
|
12
|
+
Each membership is a distinct association between a user and a seller account.
|
|
13
|
+
|
|
14
|
+
## Member Data
|
|
15
|
+
|
|
16
|
+
Each member record holds the following information:
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
| Field | Description |
|
|
20
|
+
| -------- | ------------------------------------------------------------ |
|
|
21
|
+
| `email` | The member's email address, used for login and notifications |
|
|
22
|
+
| `locale` | Preferred language/locale for the vendor portal UI |
|
|
23
|
+
| `status` | Whether the member is active or deactivated |
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
The member's identity is tied to their **email address**. Email addresses must be unique across all members within a single seller account but the same email can appear on different seller accounts.
|
|
27
|
+
|
|
28
|
+
## Member-Seller Association
|
|
29
|
+
|
|
30
|
+
When a member is added to a seller account, the association includes:
|
|
31
|
+
|
|
32
|
+
- A reference to the **seller account**
|
|
33
|
+
- A reference to the **member**
|
|
34
|
+
|
|
35
|
+
Removing the association revokes the member's access to that seller account entirely.
|
|
36
|
+
|
|
37
|
+
## Store Switcher
|
|
38
|
+
|
|
39
|
+
For users who belong to multiple seller accounts, the vendor portal provides a **store switcher**. Each store context is fully isolated — when a member switches stores, they see only the data (products, orders, payouts) belonging to that seller account.
|
|
40
|
+
|
|
41
|
+
This isolation ensures that access to one store never leaks information from another, even when the same person manages both.
|
|
42
|
+
|
|
43
|
+
## Adding Members
|
|
44
|
+
|
|
45
|
+
Members can be added to a seller account by:
|
|
46
|
+
|
|
47
|
+
- **Operators** — via the admin dashboard, an operator can add members to any seller account
|
|
48
|
+
- **Seller admins** — members with admin access can invite new members to their own seller account
|
|
49
|
+
|
|
50
|
+
When a new member is added, they receive an invitation to set up their access. If the email already belongs to an existing user in the system, the new seller association is linked to their existing account.
|
|
51
|
+
|
|
52
|
+
## Removing Members
|
|
53
|
+
|
|
54
|
+
Removing a member **deletes the association** between the user and the seller account. The user's account continues to exist — they simply lose access to that particular store.
|
|
55
|
+
|
|
56
|
+
Both **operators** and **seller admins** can remove members, subject to the constraint that a seller account must always retain at least one admin member.
|
|
57
|
+
|
|
58
|
+
## Business Rules
|
|
59
|
+
|
|
60
|
+
- A seller account must have **at least one member** with admin access at all times
|
|
61
|
+
- **Email addresses** must be unique within a single seller account
|
|
62
|
+
- Members are managed through the [seller account lifecycle](/rc/learn/sellers) — if a seller is terminated, all member associations are effectively void
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Seller"
|
|
3
|
+
description: "The central marketplace actor — seller profile, lifecycle, registration flows, and business rules."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A **seller** is the central actor in a Mercur marketplace. Every product listing, order, payout, and storefront presence traces back to a seller account. This page covers the seller data model, lifecycle, and the business rules that govern how sellers operate on the platform.
|
|
7
|
+
|
|
8
|
+
## Seller Profile
|
|
9
|
+
|
|
10
|
+
Each seller account holds the following core fields:
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
| Field | Description |
|
|
14
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
15
|
+
| `name` | Display name shown to customers on the storefront (unique) |
|
|
16
|
+
| `handle` | URL-friendly identifier for the seller (unique) |
|
|
17
|
+
| `email` | Primary contact email for the seller account (unique) |
|
|
18
|
+
| `description` | Free-text seller description, typically shown on the seller's storefront page |
|
|
19
|
+
| `logo` | Seller logo or avatar |
|
|
20
|
+
| `banner` | Banner image for the seller's storefront page |
|
|
21
|
+
| `website_url` | Seller's external website |
|
|
22
|
+
| `currency_code` | The single currency in which this seller operates |
|
|
23
|
+
| `is_premium` | Operator-designated premium seller flag (see below) |
|
|
24
|
+
| `status_reason` | Optional explanation for the current status (e.g. reason for suspension) |
|
|
25
|
+
| `external_id` | Identifier in an external system (unique, optional) |
|
|
26
|
+
| `metadata` | Arbitrary JSON metadata |
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Single Currency Per Account
|
|
30
|
+
|
|
31
|
+
Every seller account is locked to **one currency**. Prices and payouts all use this currency. This constraint keeps financial reporting simple and eliminates exchange-rate ambiguity in payouts.
|
|
32
|
+
|
|
33
|
+
If a seller needs to trade in multiple currencies, the recommended pattern is to create **separate seller accounts** — one per currency. Each account operates independently with its own products, orders, and payouts.
|
|
34
|
+
|
|
35
|
+
### Professional Sellers
|
|
36
|
+
|
|
37
|
+
A seller can optionally have associated **professional details**. If present, the seller is treated as a registered business; if absent, the seller is an individual.
|
|
38
|
+
|
|
39
|
+
## Address and Payment Information
|
|
40
|
+
|
|
41
|
+
Sellers can store one or more **addresses** (warehouse, return, business) and **payment details** used for payout processing. These are managed as sub-resources of the seller account and are referenced by workflows such as fulfillment and payout settlement.
|
|
42
|
+
|
|
43
|
+
## Seller Lifecycle
|
|
44
|
+
|
|
45
|
+
A seller account moves through **four statuses** over its lifetime:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
┌──────────────────┐
|
|
49
|
+
│ pending_approval │
|
|
50
|
+
└────────┬─────────┘
|
|
51
|
+
│ approve
|
|
52
|
+
▼
|
|
53
|
+
┌──────────┐ ┌────────┐
|
|
54
|
+
│ suspended │◄────►│ open │
|
|
55
|
+
└──────────┘ └───┬────┘
|
|
56
|
+
│ terminate
|
|
57
|
+
▼
|
|
58
|
+
┌────────────┐
|
|
59
|
+
│ terminated │
|
|
60
|
+
└────────────┘
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Status Definitions
|
|
64
|
+
|
|
65
|
+
- **`pending_approval`** — The seller has registered but has not yet been reviewed by the platform operator.
|
|
66
|
+
- **`open`** — The seller is active and may list products, receive orders, and collect payouts.
|
|
67
|
+
- **`suspended`** — The seller's operations are temporarily frozen. Products remain in the catalog but cannot be purchased.
|
|
68
|
+
- **`terminated`** — The seller account is permanently closed. This status is irreversible.
|
|
69
|
+
|
|
70
|
+
### Status Transition Rules
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
| From | To | Who | Conditions |
|
|
74
|
+
| ------------------ | ------------ | ----------------- | --------------------------------------------------------- |
|
|
75
|
+
| `pending_approval` | `open` | Operator | Operator reviews and approves the application |
|
|
76
|
+
| `open` | `suspended` | Operator | Policy violation, compliance hold, or operator discretion |
|
|
77
|
+
| `suspended` | `open` | Operator | Issue resolved, seller reinstated |
|
|
78
|
+
| `open` | `terminated` | Operator / Seller | All prerequisites met (see below) |
|
|
79
|
+
| `suspended` | `terminated` | Operator | All prerequisites met (see below) |
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## Scheduled Closures
|
|
83
|
+
|
|
84
|
+
Sellers can schedule **temporary closures** without changing their account status. Two date fields control this:
|
|
85
|
+
|
|
86
|
+
- `closed_from` — The date the closure begins
|
|
87
|
+
- `closed_to` — The date the closure ends
|
|
88
|
+
|
|
89
|
+
During a scheduled closure the seller's storefront shows as unavailable and new orders cannot be placed, but the account remains in `open` status. This is designed for holidays, seasonal breaks, or planned downtime. Once `closed_to` passes, the seller automatically resumes normal operation.
|
|
90
|
+
|
|
91
|
+
Scheduled closures are **not a status** — they overlay on top of the current status and do not affect status transition rules.
|
|
92
|
+
|
|
93
|
+
## Premium Sellers
|
|
94
|
+
|
|
95
|
+
The `is_premium` flag is set **exclusively by the platform operator**. Sellers cannot designate themselves as premium. This flag is used for storefront features such as:
|
|
96
|
+
|
|
97
|
+
- Featured placement in search results or category pages
|
|
98
|
+
- Visual badges or highlights on the seller's profile
|
|
99
|
+
- Priority in marketplace curation
|
|
100
|
+
|
|
101
|
+
The specific storefront behavior tied to premium status is determined by the frontend implementation.
|
|
102
|
+
|
|
103
|
+
## Registration Flows
|
|
104
|
+
|
|
105
|
+
There are **two methods** for creating a seller account:
|
|
106
|
+
|
|
107
|
+
1. **Operator-created** — The platform operator creates the seller account directly via the admin dashboard. The account can be set to `open` immediately, bypassing `pending_approval`.
|
|
108
|
+
2. **Self-registration** — The seller registers through the public-facing registration flow. The account enters `pending_approval` status and waits for operator review.
|
|
109
|
+
|
|
110
|
+
## Business Rules Summary
|
|
111
|
+
|
|
112
|
+
- A seller account operates in **exactly one currency**
|
|
113
|
+
- The presence of `professional_details` determines whether the seller is a registered business
|
|
114
|
+
- Only the **operator** can approve, suspend, or reinstate sellers
|
|
115
|
+
- **Termination** is irreversible and requires all orders and payouts to be resolved
|
|
116
|
+
- Scheduled closures are **date-driven** and do not change account status
|
|
117
|
+
- **Premium** designation is operator-only and influences storefront presentation
|
|
118
|
+
- Every seller account must have at least one [member](/rc/learn/seller-members) with an admin role
|