products
Search visible products and retrieve pagination and facets through GraphQL.
Last updated:
products queries the published catalog for the resolved store. Use this query for listings, search results, and collection or seller pages.
Signature
products(input: StorefrontProductsInput): SearchResult!input is optional. If omitted, the API queries the first page with pageSize: 24 and the default sort order.
Input
| Field | Type | Default | Rules |
|---|---|---|---|
productIds | [String!] | No filter | At most 100 valid opaque IDs. |
search | String | No search | At most 200 characters. |
categories | [String!] | No filter | At most 50 values and 100 characters per value. |
brands | [String!] | No filter | At most 50 values and 100 characters per value. |
sellerSlugs | [String!] | No filter | At most 20 slugs and 100 characters per slug. |
collections | [String!] | No filter | At most 50 values and 100 characters per value. |
collectionId | String | No filter | Valid opaque collection ID. |
productTypes | [ProductType!] | No filter | At most 50 values. |
tags | [String!] | No filter | At most 50 values and 100 characters per value. |
filters | [String!] | No selected facets | At most 100 filters and 250 characters per filter. |
inStock | Boolean | No filter | When true, limits results to available products. |
minPrice | Decimal | No minimum | Must be greater than or equal to 0. |
maxPrice | Decimal | No maximum | Must be greater than or equal to 0 and to minPrice. |
page | Int | 1 | Between 1 and 100. |
pageSize | Int | 24 | Between 1 and 100. |
sort | ProductSearchSort | DEFAULT | Result order. |
Each filters value uses one of these forms:
option:name:value
attribute:name:valueYou can select only one value for each product option. Attribute filters can be combined.
Enums
ProductType accepts PRODUCT, SERVICE, and BUNDLE.
ProductSearchSort accepts:
| Value | Use |
|---|---|
DEFAULT | Default catalog order. |
PRICE_ASC | Lowest price first. |
PRICE_DESC | Highest price first. |
NEWEST | Newest products first. |
NAME_ASC | Name in ascending order. |
NAME_DESC | Name in descending order. |
Return value
SearchResult contains:
| Field | Type | Description |
|---|---|---|
pageIndex | Int! | Returned page. |
pageSize | Int! | Applied page size. |
totalCount | Long! | Total number of matches. |
totalPages | Int! | Total number of pages. |
products | [ProductSummary!]! | Products in the page. |
filters | [SearchFilter!]! | Facets available to refine the query. |
ProductSummary
| Field | Type | Field | Type |
|---|---|---|---|
id | String! | name | String! |
slug | String! | productType | String! |
imageUrl | String! | price | Decimal! |
compareAtPrice | Decimal | variantCount | Int! |
isAvailable | Boolean! | totalInventory | Int! |
bundleItemsCount | Int! | brand | String! |
category | String! | status | String! |
collections | [String!]! | tags | [String!]! |
seller | ProductSellerInfo |
ProductSellerInfo contains id, name, and slug, all String!.
Filters and facets
Each SearchFilter contains:
| Field | Type | Description |
|---|---|---|
id | String! | Filter identifier. |
label | String! | Display label. |
type | String! | Filter type. |
values | [FacetItem!]! | Available values and their counts. |
min | Decimal | Available lower bound, when applicable. |
max | Decimal | Available upper bound, when applicable. |
selectedMin | Decimal | Selected lower bound, when applicable. |
selectedMax | Decimal | Selected upper bound, when applicable. |
Each FacetItem contains value: String!, count: Int!, label: String, and selected: Boolean!.
Query
query Products($input: StorefrontProductsInput) {
products(input: $input) {
pageIndex
pageSize
totalCount
totalPages
products {
id
name
slug
productType
imageUrl
price
compareAtPrice
variantCount
isAvailable
totalInventory
bundleItemsCount
brand
category
status
collections
tags
seller {
id
name
slug
}
}
filters {
id
label
type
min
max
selectedMin
selectedMax
values {
value
count
label
selected
}
}
}
}Variables:
{
"input": {
"search": "mug",
"categories": ["Home"],
"inStock": true,
"page": 1,
"pageSize": 24,
"sort": "PRICE_ASC"
}
}cURL
curl --request POST "https://storefront.ecomiq.pe/graphql" \
--header "Content-Type: application/json" \
--header "x-Store-Domain: my-store" \
--data-binary '{
"query": "query Products($input: StorefrontProductsInput) { products(input: $input) { pageIndex pageSize totalCount totalPages products { id name slug productType imageUrl price compareAtPrice variantCount isAvailable totalInventory bundleItemsCount brand category status collections tags seller { id name slug } } filters { id label type min max selectedMin selectedMax values { value count label selected } } } }",
"variables": {
"input": {
"search": "mug",
"categories": ["Home"],
"inStock": true,
"page": 1,
"pageSize": 24,
"sort": "PRICE_ASC"
}
}
}'Response
The API returns only the requested fields. This example uses the product summary values covered by the host contract:
{
"data": {
"products": {
"pageIndex": 1,
"pageSize": 24,
"totalCount": 1,
"totalPages": 1,
"products": [
{
"id": "789",
"name": "Related mug",
"slug": "related-mug",
"productType": "Product",
"imageUrl": "/related.jpg",
"price": 12,
"compareAtPrice": null,
"variantCount": 1,
"isAvailable": true,
"totalInventory": 2,
"bundleItemsCount": 0,
"brand": "Acme",
"category": "Home",
"status": "Active",
"collections": [],
"tags": [],
"seller": null
}
],
"filters": []
}
}
}Errors
| Code | Common cause |
|---|---|
BAD_USER_INPUT | Page, size, price, ID, filter, or number of values is outside the contract. |
NOT_FOUND | A requested collection does not exist or is not visible. |
STORE_CONTEXT_REQUIRED | x-Store-Domain did not resolve a store. |
A GraphQL response can include errors with HTTP 200. See GraphQL errors.