Skip to Content

products

Search for products in the catalog.

Query Structure

query { products( query: String limit: Int offset: Int sort: String productGroup: String priceMin: Float priceMax: Float onlyDiscounted: Boolean onlyNew: Boolean first: Int after: String last: Int before: String sortKey: String reverse: Boolean ) { edges { cursor node { # See Product object for fields } } nodes { # See Product object for fields } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } totalCount } }

Arguments

ArgumentTypeDescriptionRequiredDefault
queryStringSearch query stringNoNone
limitIntMaximum number of results to returnNoNone
offsetIntOffset for paginationNoNone
sortStringSort order (price-ascending, price-descending, title-ascending, title-descending, etc.)NoNone
productGroupStringFilter by product groupNoNone
priceMinFloatMinimum price filterNoNone
priceMaxFloatMaximum price filterNoNone
onlyDiscountedBooleanShow only products with discountNofalse
onlyNewBooleanShow only new productsNofalse
firstIntReturns the first n elements (cursor-based pagination)NoNone
afterStringReturns elements after cursor (cursor-based pagination)NoNone
lastIntReturns the last n elements (cursor-based pagination)NoNone
beforeStringReturns elements before cursor (cursor-based pagination)NoNone
sortKeyStringThe field to sort by. Available values: default, title, price, createdNodefault
reverseBooleanReverse the order of the underlying listNofalse

Return Type

Type: ProductConnection

A connection to a list of Product items with the following fields:

FieldTypeDescription
edges[ProductEdge]A list of edges.
nodes[Product]A list of nodes.
pageInfoPageInfoInformation about pagination.
totalCountIntThe total number of items.

ProductEdge

FieldTypeDescription
cursorStringA cursor for use in pagination.
nodeProductThe item at the end of the edge.

PageInfo

FieldTypeDescription
hasNextPageBooleanWhether there are more items after this page.
hasPreviousPageBooleanWhether there are more items before this page.
startCursorStringThe cursor of the first item in the page.
endCursorStringThe cursor of the last item in the page.

Examples

Basic Query

query { products(first: 10) { nodes { id title isAvailable } totalCount } }

Search Query

query { products(query: "shirt", first: 20) { nodes { id title description isAvailable } pageInfo { hasNextPage endCursor } totalCount } }

Filtered Query

query { products( productGroup: "clothing" priceMin: 10.00 priceMax: 100.00 onlyDiscounted: true first: 20 sortKey: "price" ) { nodes { id title handle isAvailable variants { id price compareAtPrice } } pageInfo { hasNextPage endCursor } totalCount } }

Cursor-Based Pagination

query { products(first: 10, after: "cursor_value_here") { edges { cursor node { id title isAvailable } } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } totalCount } }

Advanced Query with Sorting

query { products( query: "shoes" first: 20 sortKey: "price" reverse: true onlyNew: true ) { nodes { id title handle seoTitle seoDescription isAvailable isDirectlyBuyable tags rating reviewCount variants { id title sku price available } manufacturer { id name } productGroups { id name } createdAt updatedAt } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } totalCount } }

cURL Example

curl -X POST https://www.mystoreurl.com/graphql/0.9.0 \ -H "Content-Type: application/json" \ -d '{"query":"query { products(first: 10) { nodes { id title isAvailable } totalCount } }"}'

JavaScript Example

async function searchProducts(options = {}) { const { query = '', first = 10, after = null, productGroup = null, priceMin = null, priceMax = null, sortKey = 'default', reverse = false } = options; const graphqlQuery = ` query SearchProducts( $query: String $first: Int $after: String $productGroup: String $priceMin: Float $priceMax: Float $sortKey: String $reverse: Boolean ) { products( query: $query first: $first after: $after productGroup: $productGroup priceMin: $priceMin priceMax: $priceMax sortKey: $sortKey reverse: $reverse ) { nodes { id title description isAvailable variants { id price available } } pageInfo { hasNextPage endCursor } totalCount } } `; try { const response = await fetch('https://www.mystoreurl.com/graphql/0.9.0', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ query: graphqlQuery, variables: { query: query || null, first, after, productGroup, priceMin, priceMax, sortKey, reverse } }), }); const result = await response.json(); if (result.errors) { console.error('GraphQL errors:', result.errors); return null; } return result.data.products; } catch (error) { console.error('Network error:', error); return null; } } // Usage examples // Basic search searchProducts({ first: 10 }).then(products => { if (products) { console.log(`Found ${products.totalCount} products`); products.nodes.forEach(product => { console.log(`- ${product.title}`); }); } }); // Filtered search with pagination searchProducts({ query: 'shirt', first: 20, priceMin: 10, priceMax: 50, sortKey: 'price', reverse: false }).then(products => { if (products) { console.log('Products:', products.nodes); if (products.pageInfo.hasNextPage) { console.log('More products available, use cursor:', products.pageInfo.endCursor); } } });

Response Format

The response will contain a products object with the requested fields. Example response for a basic query:

{ "data": { "products": { "nodes": [ { "id": 12345, "title": "Example Product 1", "isAvailable": true }, { "id": 12346, "title": "Example Product 2", "isAvailable": true }, { "id": 12347, "title": "Example Product 3", "isAvailable": false } ], "totalCount": 150 } } }

Example response with pagination info:

{ "data": { "products": { "edges": [ { "cursor": "YXJyYXljb25uZWN0aW9uOjA=", "node": { "id": 12345, "title": "Example Product 1" } }, { "cursor": "YXJyYXljb25uZWN0aW9uOjE=", "node": { "id": 12346, "title": "Example Product 2" } } ], "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", "endCursor": "YXJyYXljb25uZWN0aW9uOjE=" }, "totalCount": 150 } } }

If no products match the query, nodes will be an empty array and totalCount will be 0.

Error Handling

Error CodeDescription
BAD_USER_INPUTOne or more provided arguments are invalid.
INTERNAL_SERVER_ERRORAn unexpected error occurred on the server.
RATE_LIMIT_EXCEEDEDThe client has exceeded the allowed number of requests.

Clients should check for errors in the GraphQL response’s errors array and handle accordingly.

Performance Considerations

  • Use pagination (first/after or last/before) to limit result set size.
  • Limit requested fields to only those needed to reduce response size and improve performance.
  • Avoid requesting deeply nested fields unless necessary.
  • Use filters (productGroup, priceMin, priceMax, onlyDiscounted, onlyNew) to narrow results server-side.
  • The API enforces rate limiting; clients should implement retry logic with exponential backoff.
  • Responses may be cached by clients or intermediaries; consider cache headers if provided.
  • For large catalogs, prefer cursor-based pagination (first/after) over offset-based pagination (limit/offset) for better performance.

Authentication

This API currently does not require authentication. However, authentication requirements may be introduced in future versions. Monitor API updates for any changes to authentication requirements.

Notes

  • All arguments are optional; calling products without arguments returns a default paginated list of products.
  • The query argument performs a text search across product titles and descriptions.
  • Use sortKey with values default, title, price, or created to sort results.
  • The reverse argument reverses the sort order when set to true.
  • Both offset-based (limit/offset) and cursor-based (first/after/last/before) pagination are supported.
  • Cursor-based pagination is recommended for large result sets as it provides more consistent results.
  • The totalCount field returns the total number of products matching the query, regardless of pagination limits.
  • Filter arguments can be combined to create complex queries.
  • The onlyDiscounted filter shows products where the current price is less than the compare-at price.
  • The onlyNew filter shows products marked as new in the catalog.
Last updated on