--- title: ProductSearch API description: The ProductSearch API gives extensions access to the native product search and fetching functionality of Shopify POS. The interface provides numerous functions to search for products by query, or to fetch the details of one or more products or product variants. api_version: 2025-10 api_name: pos-ui-extensions source_url: html: https://shopify.dev/docs/api/pos-ui-extensions/latest/apis/productsearch-api md: https://shopify.dev/docs/api/pos-ui-extensions/latest/apis/productsearch-api.md --- # Product​Search APIAPIs The ProductSearch API gives extensions access to the native product search and fetching functionality of Shopify POS. The interface provides numerous functions to search for products by query, or to fetch the details of one or more products or product variants. ## ProductSearchApi * fetchPaginatedProductVariantsWithProductId (productId: number, paginationParams: PaginationParams) => Promise\> required Fetches a page of product variants associated with a product. * fetchProductsWithIds (productIds: number\[]) => Promise\> required Fetches multiple products' details. * fetchProductVariantsWithIds (productVariantIds: number\[]) => Promise\> required Fetches multiple product variants' details. * fetchProductVariantsWithProductId (productId: number) => Promise\ required Fetches all product variants associated with a product. * fetchProductVariantWithId (productVariantId: number) => Promise\ required Fetches a single product variant's details. * fetchProductWithId (productId: number) => Promise\ required Fetches a single product's details. * searchProducts (searchParams: ProductSearchParams) => Promise\> required Search for products on the POS device. ### PaginationParams Base interface for pagination. * afterCursor Specifies the page cursor. Items after this cursor will be returned. ```ts string ``` * first Specifies the number of results to be returned in this page. The maximum number of items that will be returned is 50. ```ts number ``` ```ts export interface PaginationParams { /** * Specifies the number of results to be returned in this page. The maximum number of items that will be returned is 50. */ first?: number; /** * Specifies the page cursor. Items after this cursor will be returned. */ afterCursor?: string; } ``` ### PaginatedResult Contains a page of fetched results. * hasNextPage Whether or not there is another page of results that can be fetched. ```ts boolean ``` * items The items returned from the fetch. ```ts T[] ``` * lastCursor The cursor of the last item. This can be used to fetch more results. The format of this cursor may look different depending on if POS is fetching results from the remote API, or its local database. However, that should not affect its usage with the search functions. ```ts string ``` ```ts export interface PaginatedResult { /** * The items returned from the fetch. */ items: T[]; /** * The cursor of the last item. This can be used to fetch more results. * The format of this cursor may look different depending on if POS is fetching results from the remote API, or its local database. However, that should not affect its usage with the search functions. */ lastCursor?: string; /** * Whether or not there is another page of results that can be fetched. */ hasNextPage: boolean; } ``` ### ProductVariant * barcode ```ts string ``` * compareAtPrice ```ts string ``` * createdAt ```ts string ``` * displayName ```ts string ``` * hasInStockVariants ```ts boolean ``` * id ```ts number ``` * image ```ts string ``` * inventoryAtAllLocations ```ts number ``` * inventoryAtLocation ```ts number ``` * inventoryIsTracked ```ts boolean ``` * inventoryPolicy ```ts ProductVariantInventoryPolicy ``` * options ```ts ProductVariantOption[] ``` * position ```ts number ``` * price ```ts string ``` * product ```ts Product ``` * productId ```ts number ``` * sku ```ts string ``` * taxable ```ts boolean ``` * title ```ts string ``` * updatedAt ```ts string ``` ```ts export interface ProductVariant { id: number; createdAt: string; updatedAt: string; title: string; price: string; compareAtPrice?: string; taxable: boolean; sku?: string; barcode?: string; displayName: string; image?: string; inventoryIsTracked: boolean; inventoryAtLocation?: number; inventoryAtAllLocations?: number; inventoryPolicy: ProductVariantInventoryPolicy; hasInStockVariants?: boolean; options?: ProductVariantOption[]; product?: Product; productId: number; position: number; } ``` ### ProductVariantInventoryPolicy ```ts 'DENY' | 'CONTINUE' ``` ### ProductVariantOption * name ```ts string ``` * value ```ts string ``` ```ts export interface ProductVariantOption { name: string; value: string; } ``` ### Product * createdAt ```ts string ``` * description ```ts string ``` * descriptionHtml ```ts string ``` * featuredImage ```ts string ``` * hasInStockVariants ```ts boolean ``` * hasOnlyDefaultVariant ```ts boolean ``` * hasSellingPlanGroups ```ts boolean ``` * id ```ts number ``` * isGiftCard ```ts boolean ``` * maxVariantPrice ```ts string ``` * minVariantPrice ```ts string ``` * numVariants ```ts number ``` * onlineStoreUrl ```ts string ``` * options ```ts ProductOption[] ``` * productCategory ```ts string ``` * productType ```ts string ``` * requiresSellingPlan ```ts boolean ``` * tags ```ts string[] ``` * title ```ts string ``` * totalAvailableInventory ```ts number ``` * totalInventory ```ts number ``` * tracksInventory ```ts boolean ``` * updatedAt ```ts string ``` * variants ```ts ProductVariant[] ``` * vendor ```ts string ``` ```ts export interface Product { id: number; createdAt: string; updatedAt: string; title: string; description: string; descriptionHtml: string; featuredImage?: string; isGiftCard: boolean; tracksInventory: boolean; vendor: string; minVariantPrice: string; maxVariantPrice: string; productType: string; productCategory: string; tags: string[]; numVariants: number; totalAvailableInventory?: number; totalInventory: number; variants: ProductVariant[]; options: ProductOption[]; hasOnlyDefaultVariant: boolean; hasInStockVariants?: boolean; onlineStoreUrl?: string; requiresSellingPlan?: boolean; hasSellingPlanGroups?: boolean; } ``` ### ProductOption * id ```ts number ``` * name ```ts string ``` * optionValues ```ts string[] ``` * productId ```ts number ``` ```ts export interface ProductOption { id: number; name: string; optionValues: string[]; productId: number; } ``` ### MultipleResourceResult The result of a fetch function where the input is multiple IDs. This object contains the resources that were found, as well as an array of IDs specifying which IDs, if any, did not correspond to a resource. * fetchedResources The resources that were fetched using the IDs provided. ```ts T[] ``` * idsForResourcesNotFound The IDs for which a resource was not found. ```ts number[] ``` ```ts export interface MultipleResourceResult { /** * The resources that were fetched using the IDs provided. */ fetchedResources: T[]; /** * The IDs for which a resource was not found. */ idsForResourcesNotFound: number[]; } ``` ### ProductSearchParams Interface for product search * afterCursor Specifies the page cursor. Items after this cursor will be returned. ```ts string ``` * first Specifies the number of results to be returned in this page. The maximum number of items that will be returned is 50. ```ts number ``` * queryString The search term to be used to search for POS products. ```ts string ``` * sortType Specifies the order in which products should be sorted. When a \`queryString\` is provided, sortType will not have any effect, as the results will be returned in order by relevance to the \`queryString\`. ```ts ProductSortType ``` ```ts export interface ProductSearchParams extends PaginationParams { /** * The search term to be used to search for POS products. */ queryString?: string; /** * Specifies the order in which products should be sorted. When a `queryString` is provided, sortType will not have any effect, as the results will be returned in order by relevance to the `queryString`. */ sortType?: ProductSortType; } ``` ### ProductSortType ```ts 'RECENTLY_ADDED' | 'RECENTLY_ADDED_ASCENDING' | 'ALPHABETICAL_A_TO_Z' | 'ALPHABETICAL_Z_TO_A' ``` ## Examples Examples of using the Cart API Search for products with a search bar Fetch a specific product with a product ID Fetch multiple products by specifying product IDs Fetch a specific product variant with a variant ID Fetch multiple product variants by specifying variant IDs Fetch a page of product variants with a specific product ID ### Examples * #### Search for products with a search bar ##### jsx ```jsx import {render} from 'preact'; import {useState} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [searchResults, setSearchResults] = useState([]); const search = async (event) => { const results = await shopify.productSearch.searchProducts({queryString: event.target.value}); setSearchResults(results.items); }; return ( Found {searchResults.length} products ); }; ``` * #### Fetch a specific product with a product ID ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [product, setProduct] = useState(null); useEffect(() => { const fetchProduct = async () => { const resultProduct = await shopify.productSearch.fetchProductWithId(1); setProduct(resultProduct); }; fetchProduct(); }, []); return ( {product ? `Product: ${product.title}` : 'Loading...'} ); }; ``` * #### Fetch multiple products by specifying product IDs ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [products, setProducts] = useState([]); useEffect(() => { const fetchProducts = async () => { const results = await shopify.productSearch.fetchProductsWithIds([1, 2, 3]); setProducts(results.fetchedResources); console.log('IDs not found: ', results.idsForResourcesNotFound); }; fetchProducts(); }, []); return ( Found {products.length} products {products.map((product) => ( {product.title} ))} ); }; ``` * #### Fetch a specific product variant with a variant ID ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [variant, setVariant] = useState(null); useEffect(() => { const fetchProductVariant = async () => { const resultProductVariant = await shopify.productSearch.fetchProductVariantWithId(1); setVariant(resultProductVariant); }; fetchProductVariant(); }, []); return ( {variant ? `Variant: ${variant.title}` : 'Loading...'} ); }; ``` * #### Fetch multiple product variants by specifying variant IDs ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [variants, setVariants] = useState([]); useEffect(() => { const fetchProductVariants = async () => { const results = await shopify.productSearch.fetchProductVariantsWithIds([1, 2, 3]); setVariants(results.fetchedResources); console.log('IDs not found: ', results.idsForResourcesNotFound); }; fetchProductVariants(); }, []); return ( Found {variants.length} variants {variants.map((variant) => ( {variant.title} ))} ); }; ``` * #### Fetch a page of product variants with a specific product ID ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [variants, setVariants] = useState([]); useEffect(() => { const fetchProductVariants = async () => { const results = await shopify.productSearch.fetchPaginatedProductVariantsWithProductId(1, {first: 10}); setVariants(results.items); console.log('Cursor for next page: ', results.lastCursor); }; fetchProductVariants(); }, []); return ( Found {variants.length} variants {variants.map((variant) => ( {variant.title} ))} ); }; ```