---
description: 'Learn how to manage products using the admin APIs. Learn how to create, update, and delete products, and how to manage their options and variants.'
addHowToData: true
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# How to Manage Products

In this document, you’ll learn how to manage products using the admin APIs.

## Overview

Using the admin APIs, you can manage products, their options, and their variants.

### Scenario

You want to add or use the following admin functionalities:

- Manage products. This includes listing, adding, updating, and deleting products.
- Manage product options. This includes adding, updating, or deleting options.
- Manage product variants. This includes listing, adding, updating, or deleting variants.

---

## Prerequisites

### Medusa Components

It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started.

### JS Client

This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods.

If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.mdx) installed and have [created an instance of the client](../../../js-client/overview.mdx#configuration).

### Medusa React

This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods.

If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.mdx) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.mdx#usage).

### Authenticated Admin User

You must be an authenticated admin user before following along with the steps in the tutorial.

You can learn more about [authenticating as an admin user in the API reference](https://docs.medusajs.com/api/admin#authentication).

---

## List Products

You can list products as an admin using the [List Products API Route](https://docs.medusajs.com/api/admin#products_getproducts):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.list()
    .then(({ products, limit, offset, count }) => {
      console.log(products.length)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminProducts } from "medusa-react"

    const Products = () => {
      const { products, isLoading } = useAdminProducts()

      return (
        <div>
          {isLoading && <span>Loading...</span>}
          {products && !products.length && <span>No Products</span>}
          {products && products.length > 0 && (
            <ul>
              {products.map((product) => (
                <li key={product.id}>{product.title}</li>
              ))}
            </ul>
          )}
        </div>
      )
    }

    export default Products
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products`, {
      credentials: "include",
    })
    .then((response) => response.json())
    .then(({ products, limit, offset, count }) => {
      console.log(products.length)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X GET '<BACKEND_URL>/admin/products' \
    -H 'Authorization: Bearer <API_TOKEN>'
    ```

  </TabItem>
</Tabs>

This API Route doesn't require any parameters. You can pass parameters to search and filter through the retrieved products. For example, you can pass the `q` parameter which searches through product titles, descriptions, and more. You can learn more about available parameters in the [API reference](https://docs.medusajs.com/api/admin#products_getproducts).

You can also specify which fields to returns or which relations to expand using the `fields` and `expand` query parameters. You can learn more about them in the [API reference](https://docs.medusajs.com/api/admin#expanding-fields).

The request returns an array of products along with [pagination parameters](https://docs.medusajs.com/api/admin#pagination).

---

## Create a Product

You can create a product by sending a request to the [Create a Product API Route](https://docs.medusajs.com/api/admin#products_postproducts):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.create({
      title: "Shirt",
      is_giftcard: false,
      discountable: true,
      options: [
        {
          title: "Color",
        },
        {
          title: "Size",
        },
      ],
      variants: [
        {
          title: "White Small Shirt",
          prices: [
            {
              amount: 1000,
              currency_code,
            },
          ],
          options: [
            {
              value: "White",
            },
            {
              value: "Small",
            },
          ],
        },
      ],
      collection_id,
      categories: [
        {
          id: categoryId,
        },
      ],
      type: {
        value: typeValue,
      },
      tags: [
        {
          value: tagValue,
        },
      ],
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminCreateProduct } from "medusa-react"

    const CreateProduct = () => {
      const createProduct = useAdminCreateProduct()
      // ...

      const handleCreate = () => {
        createProduct.mutate({
          title: "Shirt",
          is_giftcard: false,
          discountable: true,
          options: [
            {
              title: "Color",
            },
            {
              title: "Size",
            },
          ],
          variants: [
            {
              title: "White Small Shirt",
              prices: [
                {
                  amount: 1000,
                  currency_code,
                },
              ],
              options: [
                {
                  value: "White",
                },
                {
                  value: "Small",
                },
              ],
            },
          ],
          collection_id,
          categories: [
            {
              id: categoryId,
            },
          ],
          type: {
            value: typeValue,
          },
          tags: [
            {
              value: tagValue,
            },
          ],
        })
      }

      // ...
    }

    export default CreateProduct
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "Shirt",
        options: [
          {
            title: "Color",
          },
          {
            title: "Size",
          },
        ],
        variants: [
          {
            title: "White Small Shirt",
            prices: [
              {
                amount: 1000,
                currency_code,
              },
            ],
            options: [
              {
                value: "White",
              },
              {
                value: "Small",
              },
            ],
          },
        ],
        collection_id,
        categories: [
          {
            id: categoryId,
          },
        ],
        type: {
          value: typeValue,
        },
        tags: [
          {
            value: tagValue,
          },
        ],
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    -H 'Content-Type: application/json' \
    --data-raw '{
        "title": "Shirt 2",
        "options": [
            {
                "title": "Color"
            },
            {
                "title": "Size"
            }
        ],
        "variants": [
            {
                "title": "White Shirt",
                "prices": [
                    {
                        "amount": 1000,
                        "currency_code": "USD"
                    }
                ],
                "options": [
                    {
                        "value": "White"
                    },
                    {
                        "value": "Small"
                    }
                ]
            }
        ],

        "collection_id": "<COL_ID>",
        "categories": [
            {
                "id": "<CAT_ID>"
            }
        ],
        "type": {
            "value": "<TYPE_VAL>"
        },
        "tags": [
            {
                "value": "<TAG_VAL>"
            }
        ]
    }'
    ```

  </TabItem>
</Tabs>

This API Route only requires the `title` body parameter, which is the name of the product. Other parameters passed in the example are optional. They are:

- `is_giftcard`: a boolean value that determines whether a product is a gift card. By default, it’s `false`.
- `is_discountable`: a boolean value that determines whether discounts can be applied on the product. By default, it’s `true`.
- `options`: an array of objects, each object has the required property `title`. This only defines the option names and not their values, as their values are defined within the product variant. The array length must be the same as that of the values passed for each variant.
- `variants`: an array of objects, each object has the required properties `title` and `prices`:
    - `title` is a string indicating the name of the variant.
    - `prices` is an array of objects, each indicating the different prices of the product variant. You can specify prices for different contexts, such as a price for different currencies or regions. You can learn more about possible properties to pass in a price object in the API reference.
    - `options` is an array of objects, each object requires the `value` property. `value` is a string indicating the value of the option. Each object within this array is matched with the object of the product’s `options` array at the same index. So, in the example above, the “White” value is matched with the “Color” option, and the “Small” value is matched with the “Size” option.
- `collection_id`: an optional ID of the collection to associate the product with.
- `categories`: an optional array of product category IDs to associate the product with.
- `type`: an optional object that holds a value of the type to associate the product with. If you don’t pass an ID in the object, a new product type will be created. Otherwise, the product will be associated with an existing product type.
- `tags`: an optional array of objects, each object requires the `value` property. If you don’t pass an ID in an object, a new product tag will be created. Otherwise, the product will be associated with an existing product tag.

You can learn about other available parameters in the [API reference](https://docs.medusajs.com/api/admin#products_postproducts).

The request returns the created product as an object.

### Product Handle

If you don’t pass the `handle` body parameter, the handle of the product will be automatically set to the slug version of the `title` parameter.

### Product Variant Prices

For currencies that are not zero-decimal, you must set the prices of product variants as the actual amount multiplied by a hundred.

So, in the example above, if the `amount` is set to `1000`, it means the price is actually `10`.

You can learn more about pricing and zero-decimal currencies [here](../products.mdx#storing-the-product-variants-price).

---

## Retrieve a Product

You can retrieve a single product as an admin by sending a request to the [Get a Product API Route](https://docs.medusajs.com/api/admin#products_getproductsproduct):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.retrieve(productId)
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminProduct } from "medusa-react"

    const Product = () => {
      const { 
        product, 
        isLoading, 
      } = useAdminProduct(productId)
    
      return (
        <div>
          {isLoading && <span>Loading...</span>}
          {product && <span>{product.title}</span>}
          
        </div>
      )
    }

    export default Product
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}`, {
      credentials: "include",
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X GET '<BACKEND_URL>/admin/products/<PRODUCT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>'
    ```

  </TabItem>
</Tabs>

This API Route requires the product ID to be passed as a path parameter.

The request returns the product as an object.

---

## Update a Product

You can update a product by sending a request to the [Update Product API Route](https://docs.medusajs.com/api/admin#products_postproductsproduct):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.update(productId, {
      title: "Shirt",
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminUpdateProduct } from "medusa-react"

    const UpdateProduct = () => {
      const updateProduct = useAdminUpdateProduct(
        productId
      )
      // ...

      const handleUpdate = () => {
        updateProduct.mutate({
          title: "Shirt",
        })
      }

      // ...
    }

    export default UpdateProduct
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "Shirt",
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products/<PRODUCT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "title": "Shirt"
    }'
    ```

  </TabItem>
</Tabs>

This API Route requires the product ID as a path parameter. In the request’s body, you can pass any of the product’s fields to update. In the example above, you update the `title` of the product.

You can learn about other body parameters that you can pass in the [API reference](https://docs.medusajs.com/api/admin#products_postproductsproduct).

The request returns the updated product as an object.

---

## Manage Product Options

In this section, you’ll learn how to manage the options of the product. Although you can already do that through the [Create a Product](#create-a-product) and [Update a Product](#update-a-product) API Routes explained above, you can also use API Routes specific to product options.

### Retrieve Product Options

You can retrieve a product’s options by retrieving the product either using the [List Products](#list-products) or the [Retrieve a Product](#retrieve-a-product) API Routes. The options are available under the `options` property.

### Add a Product Option

You can add a product option to a product by sending a request to the [Add Product Option API Route](https://docs.medusajs.com/api/admin#products_postproductsproductoptions):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.addOption(productId, {
      title: "Size",
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminCreateProductOption } from "medusa-react"

    const CreateProductOption = () => {
      const createOption = useAdminCreateProductOption(
        productId
      )
      // ...

      const handleCreate = () => {
        createOption.mutate({
          title: "Size",
        })
      }

      // ...
    }

    export default CreateProductOption
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/options`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "Size",
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products/<PRODUCT_ID>/options' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "title": "Size"
    }'
    ```

  </TabItem>
</Tabs>

This API Route requires the product’s ID as a path parameter. In the request body parameter, it requires passing the `title` of the option.

The request returns the updated product as an option. You can view available options under the `options` property of the product.

### Update a Product Option

You can update a product option by sending a request to the [Update Product Option API Route](https://docs.medusajs.com/api/admin#products_postproductsproductoptionsoption):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.updateOption(productId, optionId, {
      title: "Size",
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminUpdateProductOption } from "medusa-react"

    const UpdateProductOption = () => {
      const updateOption = useAdminUpdateProductOption(
        productId
      )
      // ...

      const handleUpdate = () => {
        updateOption.mutate({
          option_id,
          title: "Size",
        })
      }

      // ...
    }

    export default UpdateProductOption
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

<!-- eslint-disable max-len -->

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/options/${optionId}`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "Size",
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products/<PRODUCT_ID>/options/<OPT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "title": "Size"
    }'
    ```

  </TabItem>
</Tabs>

This API Route requires the product’s ID and the product option’s ID to be passed as a path parameter.

In the body parameters, you can update the `title` field of the product option.

The request returns the updated product as an option. You can view available options under the `options` property of the product.

### Delete a Product Option

You can delete a product option by sending a request to the [Delete Product Option API Route](https://docs.medusajs.com/api/admin#products_deleteproductsproductoptionsoption):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.deleteOption(productId, optionId)
    .then(({ option_id, object, deleted, product }) => {
      console.log(product.options)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminDeleteProductOption } from "medusa-react"

    const DeleteProductOption = () => {
      const deleteOption = useAdminDeleteProductOption(
        productId
      )
      // ...

      const handleDelete = () => {
        deleteOption.mutate(option_id)
      }

      // ...
    }

    export default DeleteProductOption
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

<!-- eslint-disable max-len -->

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/options/${optionId}`, {
      credentials: "include",
      method: "DELETE",
    })
    .then((response) => response.json())
    .then(({ option_id, object, deleted, product }) => {
      console.log(product.options)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X DELETE '<BACKEND_URL>/admin/products/<PRODUCT_ID>/options/<OPT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>'
    ```

  </TabItem>
</Tabs>

This API Route requires the product’s ID and the product option’s ID to be passed as a path parameter.

The request returns the following fields:

- `option_id`: The ID of the deleted product option.
- `product`: The updated product object. You can access remaining product options under `product.options`.
- `object`: The type of object that was deleted. In this case, the value will be `option`.
- `deleted`: A boolean value indicating whether the option was deleted.

---

## Manage Product Variants

In this section, you’ll learn how to manage the variants of the product. Although you can already do that through the [Create a Product](#create-a-product) and [Update a Product](#update-a-product) API Routes explained above, you can also use API Routes specific to product variants.

### Retrieve Product Variants

You can retrieve a product’s variants by retrieving the product either using the [List Products](#list-products) or the [Retrieve a Product](#retrieve-a-product) API Routes. The product variants are available under the `variants` property.

### Create Product Variants

You can create a product variant by sending a request to the [Create Product Variant API Route](https://docs.medusajs.com/api/admin#products_postproductsproductvariants):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.createVariant(product_id, {
      title: "White Shirt",
      prices: [
        {
          amount: 1000,
          currency_code: "USD",
        },
      ],
      options: [
        {
          option_id,
          value: "White",
        },
      ],
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminCreateVariant } from "medusa-react"

    const CreateProductVariant = () => {
      const createVariant = useAdminCreateVariant(
        productId
      )
      // ...

      const handleCreate = () => {
        createVariant.mutate({
          title: "White Shirt",
          prices: [
            {
              amount: 1000,
              currency_code: "USD",
            },
          ],
          options: [
            {
              option_id,
              value: "White",
            },
          ],
        })
      }

      // ...
    }

    export default CreateProductVariant
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/variants`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "White Shirt",
        prices: [
          {
            amount: 1000,
            currency_code: "USD",
          },
        ],
        options: [
          {
            option_id,
            value: "White",
          },
        ],
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products/<PRODUCT_ID>/variants' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
      "title": "White Shirt",
      "prices": [
        {
          "amount": 1000,
          "currency_code": "USD"
        }
      ],
      "options": [
        {
          "option_id": "<OPT_ID>",
          "value": "White"
        }
      ]
    }'
    ```

  </TabItem>
</Tabs>

This API Route requires the ID of the product as a path parameter. In the request body parameters, the following parameters are required:

- `title`: A string indicating the title of the product variant.
- `prices`: an array of objects, each object indicating the pricing of the variant in different contexts. For example, you can specify different prices for different currencies or regions. You can learn about other accepted properties within price objects in the API reference. You can also learn about formatting the `amount` property in this section.
- `options`: an array of objects, each object indicating a product option. Each object must have the following properties:
    - `option_id`: The ID of the product option.
    - `value`: A string indicating the value of the product option.

You can pass other optional parameters as well as indicated in the [API reference](https://docs.medusajs.com/api/admin#products_postproductsproductvariants).

The request returns the updated product. You can access the product’s variants under the `variants` property of the product.

### Update a Product Variant

You can update a product variant by sending a request to the [Update a Product Variant API Route](https://docs.medusajs.com/api/admin#products_postproductsproductvariantsvariant):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.updateVariant(productId, variantId, {
      title: "White Shirt",
    })
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminUpdateVariant } from "medusa-react"

    const UpdateProductVariant = () => {
      const updateVariant = useAdminUpdateVariant(
        productId
      )
      // ...

      const handleUpdate = () => {
        updateVariant.mutate({
          variant_id,
          title: "White Shirt",
        })
      }

      // ...
    }

    export default UpdateProductVariant
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

<!-- eslint-disable max-len -->

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/variants/${variantId}`, {
      credentials: "include",
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "White Shirt",
      }),
    })
    .then((response) => response.json())
    .then(({ product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X POST '<BACKEND_URL>/admin/products/<PRODUCT_ID>/variants/<VARIANT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
      "title": "White Shirt"
    }'
    ```

  </TabItem>
</Tabs>

This API Route requires the product ID and variant ID to be passed as a path parameter.

In the request body parameters, you can pass any of the variant’s attributes that you want to update. In the example above, you edit the `title` of the variant. You can refer to the [API reference](https://docs.medusajs.com/api/admin#products_postproductsproductvariantsvariant) for other possible parameters.

The request returns the updated product. You can access the product’s variants under the `variants` property of the product.

### Delete Product Variant

You can delete a product variant by sending a request to the [Delete a Product Variant API Route](https://docs.medusajs.com/api/admin#products_deleteproductsproductvariantsvariant):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.deleteVariant(productId, variantId)
    .then(({ variant_id, object, deleted, product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminDeleteVariant } from "medusa-react"

    const DeleteProductVariant = () => {
      const deleteVariant = useAdminDeleteVariant(
        productId
      )
      // ...

      const handleDelete = () => {
        deleteVariant.mutate(variant_id)
      }

      // ...
    }

    export default DeleteProductVariant
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

<!-- eslint-disable max-len -->

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}/variants/${variantId}`, {
      credentials: "include",
      method: "DELETE",
    })
    .then((response) => response.json())
    .then(({ variant_id, object, deleted, product }) => {
      console.log(product.id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X DELETE '<BACKEND_URL>/admin/products/<PRODUCT_ID>/variants/<VARIANT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>'
    ```

  </TabItem>
</Tabs>

This API Route requires the product ID and variant ID to be passed as a path parameter.

The request returns the following fields:

- `variant_id`: The ID of the deleted product variant.
- `product`: The updated product object. You can access remaining product variants under `product.variants`.
- `object`: The type of object that was deleted. In this case, the value will be `product-variant`.
- `deleted`: A boolean value indicating whether the variant was deleted.

---

## Delete a Product

You can delete a product by sending a request to the [Delete a Product API Route](https://docs.medusajs.com/api/admin#products_deleteproductsproduct):

<Tabs groupId="request-type" isCodeTabs={true}>
  <TabItem value="client" label="Medusa JS Client" default>

    ```ts
    medusa.admin.products.delete(productId)
    .then(({ id, object, deleted }) => {
      console.log(id)
    })
    ```

  </TabItem>
  <TabItem value="medusa-react" label="Medusa React">

    ```tsx
    import { useAdminDeleteProduct } from "medusa-react"

    const DeleteProduct = () => {
      const deleteProduct = useAdminDeleteProduct(
        productId
      )
      // ...

      const handleDelete = () => {
        deleteProduct.mutate()
      }

      // ...
    }

    export default DeleteProduct
    ```

  </TabItem>
  <TabItem value="fetch" label="Fetch API">

    ```ts
    fetch(`<BACKEND_URL>/admin/products/${productId}`, {
      credentials: "include",
      method: "DELETE",
    })
    .then((response) => response.json())
    .then(({ id, object, deleted }) => {
      console.log(id)
    })
    ```

  </TabItem>
  <TabItem value="curl" label="cURL">

    ```bash
    curl -L -X DELETE '<BACKEND_URL>/admin/products/<PRODUCT_ID>' \
    -H 'Authorization: Bearer <API_TOKEN>'
    ```

  </TabItem>
</Tabs>

This API Route requires passing the product ID as a path parameter.

The request returns the following fields:

- `id`: The ID of the deleted product.
- `object`: The type of object that was deleted. In this case, the value will be `product`.
- `deleted`: A boolean value indicating whether the product was deleted.

---

## See Also

- [How to manage categories](./manage-categories.mdx)
- [How to display products in the storefront](../storefront/show-products.mdx)
