The Offer module owns a seller’s listing — the binding of a shared product variant to that seller’s SKU, shipping profile, price, and inventory. Products in Mercur are master catalog records; the offer is what makes a variant purchasable from a specific seller.
Data models
Offer
Table offer, ID prefix offer. Unique on (seller_id, sku).
| Field | Type | Notes |
|---|
seller_id | text | The listing seller |
product_id | text | The master product |
variant_id | text | The listed variant |
shipping_profile_id | text | The seller’s shipping profile for this offer |
sku | text | Searchable; unique per seller |
ean / upc | text | Nullable, searchable |
created_by | text | Actor that created the offer |
variant_count | number | Computed; only populated in group_by_seller mode |
metadata | json | Nullable |
Indexes exist on variant_id, product_id, seller_id, shipping_profile_id, ean, and upc.
Links
Prices and inventory attach to the offer through links, not columns:
| Linked entity | Cardinality | Purpose |
|---|
Pricing.price | one offer — many prices | The offer’s own price set |
Inventory.inventoryItem | many-to-many (offer_inventory_item, with required_quantity, default 1) | The stock backing the offer |
Cart.lineItem / Order.orderLineItem | one offer — many items | Traces cart and order lines back to the offer they were bought from |
Product.product / productVariant, Seller, Fulfillment.shippingProfile | read-only | Resolved from the *_id columns |
Offer inventory links to the offer, not the variant. For offer-backed
order lines, variant.inventory_items is empty — always read stock through
the offer’s inventory link.
Service
OfferModuleService extends MedusaService with auto-generated CRUD, plus a grouped listing mode:
| Method | Behavior |
|---|
listOffers(filters, config) / listAndCountOffers(...) | When filters.group_by_seller is set, collapses results to one row per (product_id, seller_id) and computes variant_count per group; otherwise standard listing |
GET /admin/offers, POST /admin/offers/batch — operator visibility and bulk creation
GET/POST /vendor/offers, POST /vendor/offers/batch, POST /vendor/offers/:id/inventory-items/batch — seller listing management
GET /store/offers, GET /store/offers/:id — storefront discovery with per-offer calculated prices
Next steps