---
displayed_sidebar: jsClientSidebar
slug: /references/js-client/ProductsResource
---

import ParameterTypes from "@site/src/components/ParameterTypes"

# ProductsResource

This class is used to send requests to [Store Product API Routes](https://docs.medusajs.com/api/store#products). All its method
are available in the JS Client under the `medusa.products` property.

Products are saleable items in a store. This also includes [saleable gift cards](https://docs.medusajs.com/modules/gift-cards/storefront/use-gift-cards) in a store.
Using the methods in this class, you can filter products by categories, collections, sales channels, and more.

Related Guide: [How to show products in a storefront](https://docs.medusajs.com/modules/products/storefront/show-products).

## Properties

<ParameterTypes parameters={[
  {
    "name": "variants",
    "type": "[ProductVariantsResource](js_client.ProductVariantsResource.mdx)",
    "description": "An instance of [ProductVariantsResource](js_client.ProductVariantsResource.mdx) used to send requests to [Store Product Variant API Routes](https://docs.medusajs.com/api/store#product-variants\\_getvariants).",
    "optional": false,
    "defaultValue": "",
    "expandable": false,
    "children": []
  }
]} expandUrl="https://docs.medusajs.com/js-client/overview#expanding-fields"/>

___

## Methods

### list

Retrieves a list of products. The products can be filtered by fields such as `id` or `q` passed in the `query` parameter. The products can also be sorted or paginated.
This method can also be used to retrieve a product by its handle.

For accurate and correct pricing of the products based on the customer's context, it's highly recommended to pass fields such as
`region_id`, `currency_code`, and `cart_id` when available.

Passing `sales_channel_id` ensures retrieving only products available in the specified sales channel.
You can alternatively use a publishable API key in the request header instead of passing a `sales_channel_id`.

#### Example

To list products:

```ts
import Medusa from "@medusajs/medusa-js"
const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
medusa.products.list()
.then(({ products, limit, offset, count }) => {
  console.log(products.length);
})
```

To specify relations that should be retrieved within the products:

```ts
import Medusa from "@medusajs/medusa-js"
const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
medusa.products.list({
  expand: "variants"
})
.then(({ products, limit, offset, count }) => {
  console.log(products.length);
})
```

By default, only the first `100` records are retrieved. You can control pagination by specifying the `limit` and `offset` properties:

```ts
import Medusa from "@medusajs/medusa-js"
const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
medusa.products.list({
  expand: "variants",
  limit,
  offset
})
.then(({ products, limit, offset, count }) => {
  console.log(products.length);
})
```

#### Parameters

<ParameterTypes parameters={[
  {
    "name": "query",
    "type": "[StoreGetProductsParams](../../medusa/classes/medusa.StoreGetProductsParams.mdx)",
    "description": "Filters and pagination configurations to apply on the retrieved products.",
    "optional": true,
    "defaultValue": "",
    "expandable": false,
    "children": [
      {
        "name": "cart_id",
        "type": "`string`",
        "description": "Retrieve prices for a cart ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "category_id",
        "type": "`string`[]",
        "description": "Filter products by their associated product category's ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "collection_id",
        "type": "`string`[]",
        "description": "Filter products by their associated product collection's ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "created_at",
        "type": "[DateComparisonOperator](../../medusa/classes/medusa.DateComparisonOperator.mdx)",
        "description": "Date filters to apply on the products' `created_at` date.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": [
          {
            "name": "gt",
            "type": "`Date`",
            "description": "The filtered date must be greater than this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "gte",
            "type": "`Date`",
            "description": "The filtered date must be greater than or equal to this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "lt",
            "type": "`Date`",
            "description": "The filtered date must be less than this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "lte",
            "type": "`Date`",
            "description": "The filtered date must be less than or equal to this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          }
        ]
      },
      {
        "name": "currency_code",
        "type": "`string`",
        "description": "Retrieve prices for a currency code.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "description",
        "type": "`string`",
        "description": "Description to filter products by.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "expand",
        "type": "`string`",
        "description": "Comma-separated relations that should be expanded in the returned data.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "fields",
        "type": "`string`",
        "description": "Comma-separated fields that should be included in the returned data.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "handle",
        "type": "`string`",
        "description": "Handle to filter products by.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "id",
        "type": "`string` \\| `string`[]",
        "description": "IDs to filter products by.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "include_category_children",
        "type": "`boolean`",
        "description": "Whether to include product category children in the response.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "featureFlag": "product_categories",
        "children": []
      },
      {
        "name": "is_giftcard",
        "type": "`boolean`",
        "description": "Filter products by whether they're gift cards.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "limit",
        "type": "`number`",
        "description": "Limit the number of items returned in the list.",
        "optional": true,
        "defaultValue": "100",
        "expandable": false,
        "children": []
      },
      {
        "name": "offset",
        "type": "`number`",
        "description": "The number of items to skip when retrieving a list.",
        "optional": true,
        "defaultValue": "0",
        "expandable": false,
        "children": []
      },
      {
        "name": "order",
        "type": "`string`",
        "description": "The field to sort the data by. By default, the sort order is ascending. To change the order to descending, prefix the field name with `-`.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "q",
        "type": "`string`",
        "description": "Search term to search products' title, description, variants' title and sku, and collections' title.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "region_id",
        "type": "`string`",
        "description": "Retrieve prices for a region ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "sales_channel_id",
        "type": "`string`[]",
        "description": "Filter products by their associated sales channels' ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "tags",
        "type": "`string`[]",
        "description": "Filter products by their associated tags' value.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "title",
        "type": "`string`",
        "description": "Title to filter products by.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "type_id",
        "type": "`string`[]",
        "description": "Filter products by their associated product type's ID.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "updated_at",
        "type": "[DateComparisonOperator](../../medusa/classes/medusa.DateComparisonOperator.mdx)",
        "description": "Date filters to apply on the products' `created_at` date.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": [
          {
            "name": "gt",
            "type": "`Date`",
            "description": "The filtered date must be greater than this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "gte",
            "type": "`Date`",
            "description": "The filtered date must be greater than or equal to this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "lt",
            "type": "`Date`",
            "description": "The filtered date must be less than this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "lte",
            "type": "`Date`",
            "description": "The filtered date must be less than or equal to this value.",
            "optional": true,
            "defaultValue": "",
            "expandable": false,
            "children": []
          }
        ]
      }
    ]
  },
  {
    "name": "customHeaders",
    "type": "`Record<string, any>`",
    "description": "Custom headers to attach to the request.",
    "optional": false,
    "defaultValue": "{}",
    "expandable": false,
    "children": []
  }
]} expandUrl="https://docs.medusajs.com/js-client/overview#expanding-fields"/>

#### Returns

<ParameterTypes parameters={[
  {
    "name": "ResponsePromise",
    "type": "ResponsePromise&#60;StoreProductsListRes&#62;",
    "optional": false,
    "defaultValue": "",
    "description": "Resolves to the list of products with pagination fields.",
    "expandable": false,
    "children": [
      {
        "name": "StoreProductsListRes",
        "type": "[PaginatedResponse](../../medusa/interfaces/medusa.PaginatedResponse.mdx) & `object`",
        "description": "The list of products with pagination fields.",
        "optional": false,
        "defaultValue": "",
        "expandable": false,
        "children": [
          {
            "name": "count",
            "type": "`number`",
            "description": "The total number of items available.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "limit",
            "type": "`number`",
            "description": "The maximum number of items that can be returned in the list.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "offset",
            "type": "`number`",
            "description": "The number of items skipped before the returned items in the list.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          },
          {
            "name": "products",
            "type": "[PricedProduct](../../medusa/types/medusa.PricedProduct.mdx)[]",
            "description": "An array of products details.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          }
        ]
      }
    ]
  }
]} />

___

### retrieve

Retrieve a Product's details. For accurate and correct pricing of the product based on the customer's context, it's highly recommended to pass fields such as
`region_id`, `currency_code`, and `cart_id` when available.

Passing `sales_channel_id` ensures retrieving only products available in the current sales channel.
You can alternatively use a publishable API key in the request header instead of passing a `sales_channel_id`.

#### Example

```ts
import Medusa from "@medusajs/medusa-js"
const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
medusa.products.retrieve(productId)
.then(({ product }) => {
  console.log(product.id);
})
```

#### Parameters

<ParameterTypes parameters={[
  {
    "name": "id",
    "type": "`string`",
    "description": "The product's ID.",
    "optional": false,
    "defaultValue": "",
    "expandable": false,
    "children": []
  },
  {
    "name": "customHeaders",
    "type": "`Record<string, any>`",
    "description": "Custom headers to attach to the request.",
    "optional": false,
    "defaultValue": "{}",
    "expandable": false,
    "children": []
  }
]} expandUrl="https://docs.medusajs.com/js-client/overview#expanding-fields"/>

#### Returns

<ParameterTypes parameters={[
  {
    "name": "ResponsePromise",
    "type": "ResponsePromise&#60;StoreProductsRes&#62;",
    "optional": false,
    "defaultValue": "",
    "description": "Resolves to the product's details.",
    "expandable": false,
    "children": [
      {
        "name": "product",
        "type": "[PricedProduct](../../medusa/types/medusa.PricedProduct.mdx)",
        "description": "Product details.",
        "optional": false,
        "defaultValue": "",
        "expandable": false,
        "children": [
          {
            "name": "variants",
            "type": "[PricedVariant](../../medusa/types/medusa.PricedVariant.mdx)[]",
            "description": "The product variants and their prices.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          }
        ]
      }
    ]
  }
]} />

___

### search

Run a search query on products using the search service installed on the Medusa backend. The searching is handled through the search service, so the returned data's
format depends on the search service you're using.

#### Example

```ts
import Medusa from "@medusajs/medusa-js"
const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
medusa.products.search({
  q: "Shirt"
})
.then(({ hits }) => {
  console.log(hits.length);
})
```

#### Parameters

<ParameterTypes parameters={[
  {
    "name": "searchOptions",
    "type": "[StorePostSearchReq](../../medusa/classes/medusa.StorePostSearchReq.mdx)",
    "description": "Fields to search products.",
    "optional": false,
    "defaultValue": "",
    "expandable": false,
    "children": [
      {
        "name": "filter",
        "type": "`unknown`",
        "description": "Pass filters based on the search service.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "limit",
        "type": "`number`",
        "description": "Limit the number of products returned.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "offset",
        "type": "`number`",
        "description": "The number of products to skip when retrieving the products.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      },
      {
        "name": "q",
        "type": "`string`",
        "description": "The search query.",
        "optional": true,
        "defaultValue": "",
        "expandable": false,
        "children": []
      }
    ]
  },
  {
    "name": "customHeaders",
    "type": "`Record<string, any>`",
    "description": "Custom headers to attach to the request.",
    "optional": false,
    "defaultValue": "{}",
    "expandable": false,
    "children": []
  }
]} expandUrl="https://docs.medusajs.com/js-client/overview#expanding-fields"/>

#### Returns

<ParameterTypes parameters={[
  {
    "name": "ResponsePromise",
    "type": "ResponsePromise&#60;StorePostSearchRes&#62;",
    "optional": false,
    "defaultValue": "",
    "description": "Resolves to the list of search results. The format of the items depends on the search engine installed on the Medusa backend.",
    "expandable": false,
    "children": [
      {
        "name": "StorePostSearchRes",
        "type": "`object` & `Record<string, unknown>`",
        "description": "The list of search results.",
        "optional": false,
        "defaultValue": "",
        "expandable": false,
        "children": [
          {
            "name": "hits",
            "type": "`unknown`[]",
            "description": "Array of search results. The format of the items depends on the search engine installed on the Medusa backend.",
            "optional": false,
            "defaultValue": "",
            "expandable": false,
            "children": []
          }
        ]
      }
    ]
  }
]} />
