> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/medusajs/medusa/llms.txt
> Use this file to discover all available pages before exploring further.

# Product Module

> Learn about the Product Module and how to manage products, variants, collections, and categories in Medusa.

## 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.

<ResponseField name="id" type="string" required>
  Unique product identifier (prefix: `prod_`)
</ResponseField>

<ResponseField name="title" type="string" required>
  Product title, searchable and translatable
</ResponseField>

<ResponseField name="handle" type="string" required>
  URL-friendly identifier for the product
</ResponseField>

<ResponseField name="subtitle" type="string">
  Product subtitle, searchable and translatable
</ResponseField>

<ResponseField name="description" type="string">
  Product description, searchable and translatable
</ResponseField>

<ResponseField name="status" type="enum">
  Product status: `draft`, `proposed`, `published`, `rejected`
</ResponseField>

<ResponseField name="thumbnail" type="string">
  URL to the product thumbnail image
</ResponseField>

<ResponseField name="is_giftcard" type="boolean">
  Whether the product is a gift card (default: false)
</ResponseField>

<ResponseField name="discountable" type="boolean">
  Whether discounts can be applied (default: true)
</ResponseField>

<ResponseField name="variants" type="ProductVariant[]">
  Product variants with different options
</ResponseField>

<ResponseField name="options" type="ProductOption[]">
  Available options for variants (e.g., Size, Color)
</ResponseField>

<ResponseField name="images" type="ProductImage[]">
  Product images ordered by rank
</ResponseField>

<ResponseField name="collection" type="ProductCollection">
  Associated product collection
</ResponseField>

<ResponseField name="categories" type="ProductCategory[]">
  Associated product categories
</ResponseField>

<ResponseField name="tags" type="ProductTag[]">
  Product tags for organization
</ResponseField>

<ResponseField name="type" type="ProductType">
  Product type classification
</ResponseField>

### ProductVariant

Variants represent specific SKUs of a product with unique option combinations.

<ResponseField name="id" type="string" required>
  Unique variant identifier (prefix: `variant_`)
</ResponseField>

<ResponseField name="title" type="string" required>
  Variant title
</ResponseField>

<ResponseField name="sku" type="string">
  Stock keeping unit identifier
</ResponseField>

<ResponseField name="barcode" type="string">
  Product barcode
</ResponseField>

<ResponseField name="options" type="ProductOptionValue[]">
  Option values for this variant (e.g., Size: Large, Color: Red)
</ResponseField>

<ResponseField name="product_id" type="string" required>
  ID of the parent product
</ResponseField>

### ProductOption

Defines customizable product attributes.

<ResponseField name="id" type="string" required>
  Unique option identifier
</ResponseField>

<ResponseField name="title" type="string" required>
  Option title (e.g., "Size", "Color")
</ResponseField>

<ResponseField name="values" type="ProductOptionValue[]">
  Available values for this option
</ResponseField>

<ResponseField name="product_id" type="string" required>
  ID of the parent product
</ResponseField>

### ProductCollection

Groups products for marketing and organization.

<ResponseField name="id" type="string" required>
  Unique collection identifier
</ResponseField>

<ResponseField name="title" type="string" required>
  Collection title
</ResponseField>

<ResponseField name="handle" type="string" required>
  URL-friendly identifier
</ResponseField>

<ResponseField name="products" type="Product[]">
  Products in this collection
</ResponseField>

### ProductCategory

Hierarchical product categorization with tree structure.

<ResponseField name="id" type="string" required>
  Unique category identifier
</ResponseField>

<ResponseField name="name" type="string" required>
  Category name
</ResponseField>

<ResponseField name="handle" type="string" required>
  URL-friendly identifier
</ResponseField>

<ResponseField name="parent_category" type="ProductCategory">
  Parent category for nested hierarchies
</ResponseField>

<ResponseField name="category_children" type="ProductCategory[]">
  Child categories
</ResponseField>

<ResponseField name="rank" type="number">
  Display order within parent category
</ResponseField>

## Service Interface

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

### Retrieve Product

Retrieve a single product with related data.

<CodeGroup>
  ```typescript Example theme={null}
  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 })
  }
  ```
</CodeGroup>

<ParamField path="productId" type="string" required>
  The ID of the product to retrieve
</ParamField>

<ParamField path="config" type="FindConfig">
  Configuration for the query

  <ParamField path="relations" type="string[]">
    Relations to load (e.g., `["variants", "images", "collection"]`)
  </ParamField>

  <ParamField path="select" type="string[]">
    Fields to select from the product
  </ParamField>
</ParamField>

<ParamField path="sharedContext" type="Context">
  Shared context for the operation
</ParamField>

<ResponseField name="product" type="ProductDTO">
  The retrieved product
</ResponseField>

### List Products

List products with filtering and pagination.

<CodeGroup>
  ```typescript Example theme={null}
  const products = await productModuleService.listProducts(
    {
      status: ["published"],
      collection_id: ["pcol_123"],
    },
    {
      relations: ["variants"],
      take: 20,
      skip: 0,
    }
  )
  ```
</CodeGroup>

<ParamField path="filters" type="FilterableProductProps">
  Filters to apply

  <ParamField path="id" type="string | string[]">
    Filter by product IDs
  </ParamField>

  <ParamField path="status" type="ProductStatus[]">
    Filter by product status
  </ParamField>

  <ParamField path="collection_id" type="string[]">
    Filter by collection IDs
  </ParamField>

  <ParamField path="categories" type="object">
    Filter by category IDs
  </ParamField>

  <ParamField path="tags" type="object">
    Filter by tag values
  </ParamField>
</ParamField>

<ParamField path="config" type="FindConfig">
  Configuration including pagination

  <ParamField path="take" type="number">
    Number of products to retrieve
  </ParamField>

  <ParamField path="skip" type="number">
    Number of products to skip
  </ParamField>
</ParamField>

<ResponseField name="products" type="ProductDTO[]">
  Array of products matching the filters
</ResponseField>

### Create Products

Create one or more products with variants and options.

<CodeGroup>
  ```typescript Example theme={null}
  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" },
    ],
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateProductDTO | CreateProductDTO[]" required>
  Product data to create

  <ParamField path="title" type="string" required>
    Product title
  </ParamField>

  <ParamField path="handle" type="string">
    URL-friendly identifier (auto-generated from title if not provided)
  </ParamField>

  <ParamField path="status" type="ProductStatus">
    Product status (default: `draft`)
  </ParamField>

  <ParamField path="options" type="CreateProductOptionDTO[]">
    Product options with values
  </ParamField>

  <ParamField path="variants" type="CreateProductVariantDTO[]">
    Product variants
  </ParamField>

  <ParamField path="images" type="CreateProductImageDTO[]">
    Product images
  </ParamField>
</ParamField>

<ResponseField name="product" type="ProductDTO | ProductDTO[]">
  The created product(s)
</ResponseField>

### Update Products

Update product information.

<CodeGroup>
  ```typescript By ID theme={null}
  const product = await productModuleService.updateProducts("prod_123", {
    title: "Updated Product Title",
    status: "published",
  })
  ```

  ```typescript By Selector theme={null}
  const products = await productModuleService.updateProducts(
    { collection_id: "pcol_123" },
    { status: "published" }
  )
  ```
</CodeGroup>

### Create Product Variants

Add variants to existing products.

<CodeGroup>
  ```typescript Example theme={null}
  const variant = await productModuleService.createProductVariants({
    product_id: "prod_123",
    title: "Large / Red",
    sku: "TSHIRT-L-RED",
    options: {
      Size: "L",
      Color: "Red",
    },
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateProductVariantDTO | CreateProductVariantDTO[]" required>
  Variant data

  <ParamField path="product_id" type="string" required>
    ID of the parent product
  </ParamField>

  <ParamField path="title" type="string" required>
    Variant title
  </ParamField>

  <ParamField path="sku" type="string">
    Stock keeping unit
  </ParamField>

  <ParamField path="options" type="Record<string, string>">
    Option values (option title to value mapping)
  </ParamField>
</ParamField>

### Create Product Collections

Create product collections for grouping.

<CodeGroup>
  ```typescript Example theme={null}
  const collection = await productModuleService.createProductCollections({
    title: "Summer Collection",
    handle: "summer-collection",
    products: [
      { id: "prod_123" },
      { id: "prod_456" },
    ],
  })
  ```
</CodeGroup>

### Create Product Categories

Create hierarchical product categories.

<CodeGroup>
  ```typescript Example theme={null}
  const category = await productModuleService.createProductCategories({
    name: "Men's Clothing",
    handle: "mens-clothing",
    parent_category_id: "pcat_apparel",
    rank: 1,
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateProductCategoryDTO | CreateProductCategoryDTO[]" required>
  Category data

  <ParamField path="name" type="string" required>
    Category name
  </ParamField>

  <ParamField path="handle" type="string">
    URL-friendly identifier (auto-generated from name if not provided)
  </ParamField>

  <ParamField path="parent_category_id" type="string">
    ID of parent category for nesting
  </ParamField>

  <ParamField path="rank" type="number">
    Display order within parent
  </ParamField>
</ParamField>

## Integration Examples

### With Pricing Module

Product variants are linked to prices through the Pricing Module.

<CodeGroup>
  ```typescript Example theme={null}
  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: {},
        },
      ],
    },
  ])
  ```
</CodeGroup>

### With Inventory Module

Track inventory levels for product variants.

<CodeGroup>
  ```typescript Example theme={null}
  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,
  })
  ```
</CodeGroup>

### With Sales Channel Module

Associate products with sales channels for multi-channel selling.

<CodeGroup>
  ```typescript Example theme={null}
  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
  ```
</CodeGroup>

## 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.

## Related Modules

* [Pricing Module](/modules/pricing) - Manage product variant prices
* [Inventory Module](/modules/inventory) - Track variant inventory
* [Sales Channel Module](/modules/sales-channel) - Multi-channel product availability
* [Cart Module](/modules/cart) - Add products to shopping carts
* [Order Module](/modules/order) - Process product orders
