Skip to main content

Overview

The Product Module manages products and their associated data including variants, options, collections, categories, tags, and types. It provides a flexible catalog system that supports complex product hierarchies and customization. Key Features:
  • Product and variant management with options
  • Product collections and categories (tree structure)
  • Product images with variant-specific associations
  • Product tags and types for organization
  • Multi-language support with translations
  • Handle-based URLs for SEO

When to Use

Use the Product Module when you need to:
  • Create and manage product catalogs
  • Organize products with collections and categories
  • Handle product variants with multiple options (size, color, etc.)
  • Manage product images and metadata
  • Support multi-language product content
  • Track product status (draft, published, rejected)

Data Models

Product

The core product entity that represents a sellable item.
id
string
required
Unique product identifier (prefix: prod_)
title
string
required
Product title, searchable and translatable
handle
string
required
URL-friendly identifier for the product
subtitle
string
Product subtitle, searchable and translatable
description
string
Product description, searchable and translatable
status
enum
Product status: draft, proposed, published, rejected
thumbnail
string
URL to the product thumbnail image
is_giftcard
boolean
Whether the product is a gift card (default: false)
discountable
boolean
Whether discounts can be applied (default: true)
variants
ProductVariant[]
Product variants with different options
options
ProductOption[]
Available options for variants (e.g., Size, Color)
images
ProductImage[]
Product images ordered by rank
collection
ProductCollection
Associated product collection
categories
ProductCategory[]
Associated product categories
tags
ProductTag[]
Product tags for organization
type
ProductType
Product type classification

ProductVariant

Variants represent specific SKUs of a product with unique option combinations.
id
string
required
Unique variant identifier (prefix: variant_)
title
string
required
Variant title
sku
string
Stock keeping unit identifier
barcode
string
Product barcode
options
ProductOptionValue[]
Option values for this variant (e.g., Size: Large, Color: Red)
product_id
string
required
ID of the parent product

ProductOption

Defines customizable product attributes.
id
string
required
Unique option identifier
title
string
required
Option title (e.g., “Size”, “Color”)
values
ProductOptionValue[]
Available values for this option
product_id
string
required
ID of the parent product

ProductCollection

Groups products for marketing and organization.
id
string
required
Unique collection identifier
title
string
required
Collection title
handle
string
required
URL-friendly identifier
products
Product[]
Products in this collection

ProductCategory

Hierarchical product categorization with tree structure.
id
string
required
Unique category identifier
name
string
required
Category name
handle
string
required
URL-friendly identifier
parent_category
ProductCategory
Parent category for nested hierarchies
category_children
ProductCategory[]
Child categories
rank
number
Display order within parent category

Service Interface

The Product Module service is available at @medusajs/medusa/product.

Retrieve Product

Retrieve a single product with related data.
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { IProductModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"

export async function GET(
  req: MedusaRequest,
  res: MedusaResponse
) {
  const productModuleService: IProductModuleService = req.scope.resolve(
    Modules.PRODUCT
  )

  const product = await productModuleService.retrieveProduct("prod_123", {
    relations: ["variants", "images", "variants.images"],
  })

  res.json({ product })
}
productId
string
required
The ID of the product to retrieve
config
FindConfig
Configuration for the query
relations
string[]
Relations to load (e.g., ["variants", "images", "collection"])
select
string[]
Fields to select from the product
sharedContext
Context
Shared context for the operation
product
ProductDTO
The retrieved product

List Products

List products with filtering and pagination.
const products = await productModuleService.listProducts(
  {
    status: ["published"],
    collection_id: ["pcol_123"],
  },
  {
    relations: ["variants"],
    take: 20,
    skip: 0,
  }
)
filters
FilterableProductProps
Filters to apply
id
string | string[]
Filter by product IDs
status
ProductStatus[]
Filter by product status
collection_id
string[]
Filter by collection IDs
categories
object
Filter by category IDs
tags
object
Filter by tag values
config
FindConfig
Configuration including pagination
take
number
Number of products to retrieve
skip
number
Number of products to skip
products
ProductDTO[]
Array of products matching the filters

Create Products

Create one or more products with variants and options.
const product = await productModuleService.createProducts({
  title: "Medusa T-Shirt",
  handle: "medusa-tshirt",
  status: "published",
  options: [
    {
      title: "Size",
      values: ["S", "M", "L", "XL"],
    },
    {
      title: "Color",
      values: ["Black", "White"],
    },
  ],
  variants: [
    {
      title: "Small / Black",
      sku: "TSHIRT-S-BLK",
      options: {
        Size: "S",
        Color: "Black",
      },
    },
    {
      title: "Small / White",
      sku: "TSHIRT-S-WHT",
      options: {
        Size: "S",
        Color: "White",
      },
    },
  ],
  images: [
    { url: "https://example.com/tshirt.jpg" },
  ],
})
data
CreateProductDTO | CreateProductDTO[]
required
Product data to create
title
string
required
Product title
handle
string
URL-friendly identifier (auto-generated from title if not provided)
status
ProductStatus
Product status (default: draft)
options
CreateProductOptionDTO[]
Product options with values
variants
CreateProductVariantDTO[]
Product variants
images
CreateProductImageDTO[]
Product images
product
ProductDTO | ProductDTO[]
The created product(s)

Update Products

Update product information.
const product = await productModuleService.updateProducts("prod_123", {
  title: "Updated Product Title",
  status: "published",
})

Create Product Variants

Add variants to existing products.
const variant = await productModuleService.createProductVariants({
  product_id: "prod_123",
  title: "Large / Red",
  sku: "TSHIRT-L-RED",
  options: {
    Size: "L",
    Color: "Red",
  },
})
data
CreateProductVariantDTO | CreateProductVariantDTO[]
required
Variant data
product_id
string
required
ID of the parent product
title
string
required
Variant title
sku
string
Stock keeping unit
options
Record<string, string>
Option values (option title to value mapping)

Create Product Collections

Create product collections for grouping.
const collection = await productModuleService.createProductCollections({
  title: "Summer Collection",
  handle: "summer-collection",
  products: [
    { id: "prod_123" },
    { id: "prod_456" },
  ],
})

Create Product Categories

Create hierarchical product categories.
const category = await productModuleService.createProductCategories({
  name: "Men's Clothing",
  handle: "mens-clothing",
  parent_category_id: "pcat_apparel",
  rank: 1,
})
data
CreateProductCategoryDTO | CreateProductCategoryDTO[]
required
Category data
name
string
required
Category name
handle
string
URL-friendly identifier (auto-generated from name if not provided)
parent_category_id
string
ID of parent category for nesting
rank
number
Display order within parent

Integration Examples

With Pricing Module

Product variants are linked to prices through the Pricing Module.
import { Modules } from "@medusajs/framework/utils"

// Create product with variants
const product = await productModuleService.createProducts({
  title: "T-Shirt",
  variants: [
    { title: "Small", sku: "TSHIRT-S" },
    { title: "Medium", sku: "TSHIRT-M" },
  ],
})

// Add prices for variants (in a workflow)
const pricingModule = container.resolve(Modules.PRICING)

await pricingModule.createPriceSets([
  {
    prices: [
      {
        amount: 2000,
        currency_code: "usd",
        rules: {},
      },
    ],
  },
])

With Inventory Module

Track inventory levels for product variants.
import { Modules } from "@medusajs/framework/utils"

const inventoryModule = container.resolve(Modules.INVENTORY)

// Create inventory item for variant
const inventoryItem = await inventoryModule.createInventoryItems({
  sku: "TSHIRT-S",
})

// Update inventory level
await inventoryModule.updateInventoryLevels({
  inventory_item_id: inventoryItem.id,
  location_id: "sloc_warehouse",
  stocked_quantity: 100,
})

With Sales Channel Module

Associate products with sales channels for multi-channel selling.
import { Modules } from "@medusajs/framework/utils"

const salesChannelModule = container.resolve(Modules.SALES_CHANNEL)

// Products can be filtered by sales channel through links
// established in workflows or via the Link Modules

Best Practices

  1. Handle Generation: Always use URL-friendly handles for SEO. If not provided, handles are auto-generated from titles using kebab-case.
  2. Variant Options: Ensure all variants have valid option combinations. The module validates that option values match the product’s defined options.
  3. Image Management: Use the rank field on images to control display order. Variants can have specific images through the variant-image relationship.
  4. Status Management: Use draft status for products being prepared, published for active products, and rejected for products that failed review.
  5. Category Hierarchy: Design your category tree structure before implementation. Use the rank field to control sibling category order.
  6. Translations: Leverage translatable fields (title, description, subtitle, material) for multi-language support.

Build docs developers (and LLMs) love