Products
Paginated list of catalog products. The response is a slim card-level payload — fields needed to render listing/grid/search results. For the full PDP shape (categories, variants, bundle options, booking config, customizable options, related products, …) use Single Product.
Endpoint
GET /api/shop/productsThis same endpoint also powers all filtering, sorting and search — see Search Products for the full set of query parameters.
Request Headers
| Header | Required | Description |
|---|---|---|
Accept | Yes | application/json |
X-STOREFRONT-KEY | Yes | Storefront API key (pk_storefront_…) |
X-Locale | No | Override request locale |
X-Channel | No | Override channel scope |
X-Currency | No | Override currency in formattedPrice etc. |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
per_page | integer | 30 | Items per page. Capped at 50. |
For all filter / search / sort parameters (query, sort, type, category_id, price, attribute filters …) see Search Products.
Pagination headers (X-Total-Count, X-Page, X-Per-Page, X-Total-Pages) are always emitted — see Pagination.
Card-level fields
These ~20 fields are returned for every product in the list. The PDP endpoint returns these plus every related resource inlined.
| Field | Type | Description |
|---|---|---|
id | integer | Product primary key |
sku | string | Stock-keeping unit |
type | string | simple, configurable, bundle, grouped, virtual, downloadable, booking |
bookingType | string | null | When type = booking: default, appointment, rental, event, table — otherwise null |
name | string | Localized name |
urlKey | string | URL slug |
status | boolean | Whether the product is published |
shortDescription | string | Short marketing description |
price | number | Default price |
specialPrice | number | null | Sale price when in promotion window |
new | boolean | "New" flag set in admin |
featured | boolean | "Featured" flag set in admin |
minimumPrice | number | Lowest price across variants (configurable / bundle) |
maximumPrice | number | Highest price across variants |
formattedPrice | string | Currency-formatted price |
formattedSpecialPrice | string | null | Currency-formatted specialPrice |
formattedMinimumPrice | string | Currency-formatted minimumPrice |
formattedMaximumPrice | string | Currency-formatted maximumPrice |
baseImageUrl | string | null | Primary thumbnail URL |
isInWishlist | integer (0/1) | 1 if this product is in the signed-in customer's wishlist (active channel), else 0. 0 for guests. |
isInCompare | integer (0/1) | 1 if this product is in the signed-in customer's compare list, else 0. 0 for guests. |
Heavy relations (
images,videos,categories,channels,variants,bookingProducts,bundleOptions,customizableOptions,relatedProducts, etc.) are omitted from the list response. Fetch the Single Product to get them inlined.
Wishlist & compare flags
Every product card carries two per-customer booleans, isInWishlist and isInCompare, so you can render the wishlist and compare icon states straight from the listing response.
Why they exist: the wishlist and compare lists are their own endpoints and paginate independently of the catalog — a product on catalog page 1 may have its wishlist entry on a different wishlist page, so matching the two lists on the client is unreliable. These flags answer the question per product, in the same response, so the wishlist/compare icon can be highlighted without any extra requests.
- Authentication is required. Include the customer Bearer token alongside the storefront key. For guests (no customer token) both flags are always
0. isInWishlistis scoped to the active channel;isInCompareapplies across the store.- A product is flagged (
1) when its own product ID is in the customer's wishlist / compare list — so a configurable parent is flagged when the parent itself was added. - The REST API returns these as
1/0integers. (Over GraphQL the same flags are returned as the strings"1"/"0".)
Use Cases
- Render a category page / grid view / search results with paginated cards.
- Implement infinite scroll using
?page=N&per_page=20andX-Total-Pages. - Pre-load the next page based on
X-Page < X-Total-Pages.
Related Resources
- Single Product — full PDP-ready document with every relation embedded
- Search Products — full filter / sort / search reference
- Booking Slots — runtime availability for
bookingproducts - Categories —
?category_id=Nto scope by category - Attributes — discover filterable attribute codes

