One product, sold through offers
A master product is Medusa’s nativeProduct model (table product, id prefix prod). It holds the shared catalog data: title, handle, description, status, images, options, variants, and categories. It has no seller column. Creating a product adds it to the catalog, and stores then sell it by creating offers against its variants.
The split between the two records works like this:
- Master product: what the item is, shared by every store that sells it
- Offer: how one store sells it, with the store’s own SKU, price, stock, and shipping profile
inventory_items stay empty for marketplace sales.
Attribution instead of ownership
Mercur records who submitted a product without making them its owner.createProductsWorkflow takes a required created_by and writes a confirmed ProductChange with that value as created_by, holding one PRODUCT_ADD action. The action’s details store the starting status and the ids of the attributes the product began with.
The vendor API passes the store’s seller id as created_by, and the admin API passes the operator’s user id. Mercur reads that record back to decide which products a store submitted:
draft and proposed submissions, which other stores never see.
Attribution grants visibility, not control of the catalog entry. Every edit a store makes through the vendor API, to its own submission or to a published product, goes through the product edit pipeline.
What a store sees
The vendor API filters product reads by status, attribution, and the allowlist. A store’s product list contains:- Its own submissions: products it created that are
draftorproposed - Published products open to it:
publishedproducts whose allowlist is empty or includes the store
rejected products by id, but rejected products drop out of its list. The Store API returns published products only.
Related
- Status lifecycle for how a submission becomes a published product
- Create a master product to run the create workflow from your code
- Offers for how stores sell a master product