Retrieve Product Variant's Inventory in Storefront
In this guide, you'll learn how to retrieve a product variant's inventory quantity in a storefront.
How to Retrieve a Product Variant's Inventory Quantity?#
To retrieve variants' inventory quantity using either the List Products or Retrieve Products API routes:
- Pass in the
fieldsquery parameter the value+variants.inventory_quantity.- When also retrieving prices, make sure to include
*variants.calculated_pricein the beginning of the list of fields. For example,?fields=*variants.calculated_price,+variants.inventory_quantity.
- When also retrieving prices, make sure to include
- Pass the publishable API key in the header of the request, which you always do when sending a request to the Store API. The inventory quantity is retrieved based on the stock locations of the sales channels that belong to the API key's scope.
- If you're using the JS SDK, the publishable API key is automatically passed in the header of the requests as explained in the Publishable API Keys guide.
For example:
*variants.calculated_price in fields to get the product variants' prices, make sure to include it in the beginning of the list of fields. For example, ?fields=*variants.calculated_price,+variants.inventory_quantity.In this example, you retrieve the product variants' inventory quantity by passing +variants.inventory_quantity in the fields query parameter. This will add a new inventory_quantity field to each variant object.
When is a Variant in Stock?#
A variant is in stock if:
- Its
manage_inventory's value isfalse, meaning that Medusa doesn't keep track of its inventory. - If its
inventory_quantity's value is greater than0.- This property is only available on variants whose
manage_inventoryistrue. inventory_quantitycan be one of three values:null: the variant has no inventory item linked to it.0: the variant has an inventory item, but no available quantity at stock locations linked to the publishable API key's sales channel. This happens when the stock location is not linked to the sales channel, or when all stock is reserved.- A positive number: the total available quantity across stock locations linked to the sales channel.
- Availability is determined by the stock locations linked to the sales channel associated with the publishable API key. The region does not affect which stock locations are used.
- This property is only available on variants whose
Full React Example#
For example, to show on a product's page whether a variant is in stock in a React-based storefront:
1"use client" // include with Next.js 13+2 3import { useEffect, useMemo, useState } from "react"4import { HttpTypes } from "@medusajs/types"5import { sdk } from "@/lib/sdk"6 7type Props = {8 id: string9}10 11export default function Product({ id }: Props) {12 const [loading, setLoading] = useState(true)13 const [product, setProduct] = useState<14 HttpTypes.StoreProduct | undefined15 >()16 const [selectedOptions, setSelectedOptions] = useState<Record<string, string>>({})17 18 useEffect(() => {19 if (!loading) {20 return 21 }22 23 sdk.store.product.retrieve(id, {24 fields: `*variants.calculated_price,+variants.inventory_quantity`,25 })26 .then(({ product: dataProduct }) => {27 setProduct(dataProduct)28 setLoading(false)29 })30 }, [loading])31 32 const selectedVariant = useMemo(() => {33 if (34 !product?.variants ||35 !product.options || 36 Object.keys(selectedOptions).length !== product.options?.length37 ) {38 return39 }40 41 return product.variants.find((variant) => variant.options?.every(42 (optionValue) => optionValue.value === selectedOptions[optionValue.option_id!]43 ))44 }, [selectedOptions, product])45 46 const isInStock = useMemo(() => {47 if (!selectedVariant) {48 return undefined49 }50 51 return selectedVariant.manage_inventory === false || 52 (selectedVariant.inventory_quantity || 0) > 053 }, [selectedVariant])54 55 return (56 <div>57 {loading && <span>Loading...</span>}58 {product && (59 <>60 <h1>{product.title}</h1>61 {(product.options?.length || 0) > 0 && (62 <ul>63 {product.options!.map((option) => (64 <li key={option.id}>65 {option.title}66 {option.values?.map((optionValue) => (67 <button 68 key={optionValue.id}69 onClick={() => {70 setSelectedOptions((prev) => {71 return {72 ...prev,73 [option.id!]: optionValue.value!,74 }75 })76 }}77 >78 {optionValue.value}79 </button>80 ))}81 </li>82 ))}83 </ul>84 )}85 {selectedVariant && (86 <span>Selected Variant: {selectedVariant.id}</span>87 )}88 {isInStock !== undefined && (89 <span>90 {isInStock && "In Stock"}91 {!isInStock && "Out of Stock"}92 </span>93 )}94 </>95 )}96 </div>97 )98}
In this example, you retrieve the product variants' inventory quantity by passing +variants.inventory_quantity in the fields query parameter. This will add a new inventory_quantity field to each variant object.
Then, you find the selected variant and show whether it's in stock. The variant is in stock if its manage_inventory property is disabled, or the inventory_quantity is greater than 0.