Single Product
About
The product query returns one product's full detail, looked up by ID, SKU, or URL key. Use it to:
- Render a product detail page
- Resolve a storefront slug straight to a product, with no ID lookup first
- Read pricing, descriptions, images, variants, and SEO metadata in one call
- Read the type-specific structure of a bundle, grouped, downloadable, or booking product
Every product type shares the same core fields — name, sku, price, images, attributeValues — and is fetched with the same query. What differs is the type-specific connection each one populates: variants and superAttributeOptions for configurable, bundleOptions for bundle, groupedProducts for grouped, downloadableLinks for downloadable, and bookingProducts for booking. Booking goes one level further — each of its five sub-types (Appointment, Rental, Default, Table, Event) exposes a different slot relationship, which is why each has its own dropdown example.
Select only the fields you need. The full field list is in Product Fields Reference and Product Relationships Reference below.
Arguments
Supply exactly one of id, sku, or urlKey to identify the product.
| Argument | Type | Description |
|---|---|---|
id | ID | Product identifier — IRI (/api/shop/products/1) or numeric (1). |
sku | String | Stock Keeping Unit. Alternative lookup. |
urlKey | String | URL-friendly product slug. Alternative lookup. Matched across all locales — a slug created in any locale resolves regardless of the request's locale. |
locale | String | Locale for translated values. Overrides the X-Locale header for this query. |
channel | String | Channel to read the product against. Overrides the X-Channel header for this query. |
There are no arguments for including or excluding parts of the response — GraphQL field selection already controls that. Ask for images and you get images; leave it out and you do not.
Configurable Products
A configurable product is a product that has multiple variants based on attributes like color, size, or material. For example, a T-shirt that comes in 3 colors and 2 sizes would have 6 variants. When querying a configurable product, two additional fields are returned that are essential for building a variant selection UI:
Selectable options — superAttributeOptions
This field returns a JSON-encoded string containing the configurable attributes and their selectable options. Each entry includes:
code— the attribute code (e.g.color,size)label— the display label (e.g.Color,Size)options— an array of available values, each with anidandlabel
Use this field to render attribute dropdowns (e.g. color picker, size selector) on the product detail page.
Variant map — combinations
This field returns a JSON-encoded object that maps each variant product ID to its specific attribute option combination. For example:
{"8": {"color": 3, "size": 7}, "9": {"color": 3, "size": 8}}This means variant ID 8 is the product with color option 3 and size option 7. When a customer selects a color and size from the dropdowns, use this mapping to resolve which variant ID to load (for pricing, stock, images, etc.).
How they work together
- Use
superAttributeOptionsto render the attribute dropdowns on your product page - When the customer selects options (e.g. Color: Blue, Size: M), match their selection against the
combinationsobject to find the corresponding variant ID - Use that variant ID to display the correct price, stock status, and images for the selected variant
For non-configurable product types (simple, grouped, bundle, and the rest), both superAttributeOptions and combinations are null.
Downloadable Products
A downloadable product contains digital files that customers can download after purchase. Each downloadable product can have two types of sample files:
Purchasable files — downloadableLinks
These are the individual download links that make up the product (e.g. Track 1, Track 2 for a music album, or Chapter 1, Chapter 2 for an e-book). Each link has its own price and can optionally have a sample file attached for preview. The fields sampleFile, sampleFileUrl, and sampleUrl provide details about the sample associated with each link.
Product-level samples — downloadableSamples
These are product-level samples — general preview files for the entire product rather than a specific link. The _id from each sample node is used to download the sample via:
GET /api/shop/downloadable/download-sample/sample/{_id}Downloading purchased files
After a customer purchases a downloadable product, the purchased files can be downloaded using the _id from the Get Downloadable Products query (not the product query). See the Download Downloadable Product page for full details.
Sample downloads are free and need no authentication. Purchased file downloads require customer authentication and are capped at a limited number of downloads.
Grouped Products
A grouped product bundles multiple simple products together, allowing customers to purchase them as a set. Unlike a bundle product where the customer selects options, a grouped product presents each child product with a default quantity that the customer can adjust before adding to cart.
Associated children — groupedProducts
This field returns the list of associated child products via the groupedProducts connection. Each node contains:
id— the grouped product relationship IDqty— the default quantity for that child product in the groupsortOrder— the display order of the child productassociatedProduct— the full child product details includingid,name,sku,price,formattedPrice,specialPrice,formattedSpecialPrice, andimages
Pricing behavior
A grouped product's own price is always 0 because it does not have a standalone price. Instead, the price range is derived from its child products:
minimumPrice— the lowest priced child productmaximumPrice— the highest priced child product
The customer's total depends on which child products they select and in what quantities.
For non-grouped product types, groupedProducts returns an empty edges array.
Booking Product Types
All standard product types (simple, configurable, grouped, bundle, downloadable, virtual) share the same core fields and can be queried using any of the general examples above. Booking products, however, require special attention because each booking type exposes a different relationship with its own unique fields through the bookingProducts connection.
The bookingProducts field returns a type that determines which slot/ticket relationship contains the data:
| Booking Type | Relationship Field | Key Fields | Use Case |
|---|---|---|---|
| Appointment | appointmentSlot | duration, breakTime, sameSlotAllDays, slots | Salon visits, doctor appointments, consultations |
| Rental | rentalSlot | rentingType, dailyPrice, hourlyPrice, slots | Equipment rental, vehicle hire, venue booking |
| Default | defaultSlot | bookingType, duration, breakTime, slots | General time-slot bookings |
| Table | tableSlot | priceType, guestLimit, duration, breakTime, preventSchedulingBefore, slots | Restaurant reservations, meeting rooms |
| Event | eventTickets | price, qty, specialPrice, specialPriceFrom, specialPriceTo | Concerts, workshops, conferences |
Only the relationship matching the product's booking type carries data — an appointment product populates appointmentSlot and leaves rentalSlot and tableSlot empty. Read the type field first to decide which relationship to query.
Starting-from price
Each bookingProducts node also exposes a computed "starting from" price — the product base price plus the cheapest bookable extra — matching what the storefront shows on the product card / detail page:
| Field | Meaning |
|---|---|
startingPrice | Final (post-discount) starting price. |
formattedStartingPrice | Currency-formatted startingPrice. |
startingRegularPrice | Pre-discount starting price. Differs from startingPrice only when an event ticket is on sale — use both to render a strike-through. |
formattedStartingRegularPrice | Currency-formatted startingRegularPrice. |
The extra is the cheapest event ticket (for event) or the minimum rental unit rate (for rental, whichever of hourly/daily is smallest). For default, appointment and table there is no composed extra, so all four fields are null and the product's own price is the correct figure.
Product Fields Reference
Below is a complete reference of all available fields on the Product type. Use this as a lookup when building your queries — include only the fields you need.
Basic Information
| Field | Type | Description |
|---|---|---|
id | ID! | Unique product identifier in IRI format (e.g. /api/shop/products/1) |
_id | Int! | Numeric database ID |
sku | String! | Stock Keeping Unit — unique product code for inventory tracking |
type | String! | Product type: simple, virtual, configurable, grouped, bundle, downloadable, booking |
name | String | Product display name |
urlKey | String | URL-friendly slug (e.g. premium-wireless-headphones) |
status | String | Product status (1 = active, 0 = inactive) |
locale | String | Locale of the returned product data |
channel | String | Channel the product belongs to |
productNumber | String | Optional product number assigned by the store |
additional | Iterable | Additional product data stored as key-value pairs |
createdAt | String | Product creation timestamp |
updatedAt | String | Last modification timestamp |
Descriptions
| Field | Type | Description |
|---|---|---|
description | String | Full product description (plain text) |
descriptionHtml | String | Full product description with HTML formatting preserved |
shortDescription | String | Brief product summary for listing pages |
Pricing
| Field | Type | Description |
|---|---|---|
price | String | Base catalog price. Reflects active currency conversion. |
specialPrice | String | Discounted price if set, otherwise null |
specialPriceFrom | String | Start date for the special price (YYYY-MM-DD) |
specialPriceTo | String | End date for the special price (YYYY-MM-DD) |
cost | String | Product cost/purchase price (internal use) |
minimumPrice | String | Lowest effective price — accounts for special price and variant pricing. Used for price sorting. |
maximumPrice | String | Highest effective price across all variants |
regularMinimumPrice | String | Regular (non-discounted) minimum price |
regularMaximumPrice | String | Regular (non-discounted) maximum price |
formattedPrice | String | price with currency symbol (e.g. $99.00) |
formattedSpecialPrice | String | specialPrice with currency symbol |
formattedMinimumPrice | String | minimumPrice with currency symbol |
formattedMaximumPrice | String | maximumPrice with currency symbol |
formattedRegularMinimumPrice | String | regularMinimumPrice with currency symbol |
formattedRegularMaximumPrice | String | regularMaximumPrice with currency symbol |
taxCategoryId | String | Tax category ID assigned to the product |
Physical Dimensions
| Field | Type | Description |
|---|---|---|
weight | String | Product weight |
length | String | Product length |
width | String | Product width |
height | String | Product height |
Attributes
| Field | Type | Description |
|---|---|---|
color | String | Color attribute value (if applicable) |
size | String | Size attribute value (if applicable) |
brand | String | Brand attribute value (if applicable) |
SEO
| Field | Type | Description |
|---|---|---|
metaTitle | String | SEO meta title for the product page |
metaKeywords | String | SEO meta keywords |
metaDescription | String | SEO meta description |
Flags & Settings
| Field | Type | Description |
|---|---|---|
isSaleable | String | Whether the product can be purchased (1 = yes) |
new | String | Whether the product is marked as "new" (1 = yes) |
featured | String | Whether the product is featured (1 = yes) |
visibleIndividually | String | Whether the product appears in catalog listings (1 = yes) |
guestCheckout | String | Whether guest users can purchase this product (1 = yes) |
manageStock | String | Whether stock is managed for this product (1 = yes) |
isInWishlist | String | Whether the product is in the signed-in customer's wishlist for the active channel ("1" = yes). Needs the customer Bearer token; always "0" for guests. |
isInCompare | String | Whether the product is in the signed-in customer's compare list ("1" = yes). Needs the customer Bearer token; always "0" for guests. |
bookingType | String | Booking sub-type for booking products (appointment, rental, default, table, event). null for every other type. |
Configurable Product Fields
| Field | Type | Description |
|---|---|---|
superAttributeOptions | String | JSON-encoded array of configurable attributes and their selectable options. See Configurable Products. |
combinations | String | JSON-encoded object mapping variant IDs to their attribute option combinations. See Configurable Products. |
Media
| Field | Type | Description |
|---|---|---|
baseImageUrl | String | URL of the product's primary/base image |
Product Relationships Reference
These are the connection/relationship fields available on the Product type. Each returns a paginated cursor connection supporting first, last, before, and after arguments.
Core Relationships
| Relationship | Return Type | Description |
|---|---|---|
images | ProductImagesCursorConnection | Product gallery images with id, publicPath, and position |
videos | ProductVideosCursorConnection | Product videos |
categories | CategoryCursorConnection | Categories the product belongs to, with translation { name } |
attributeValues | AttributeValueCursorConnection | All attribute values with value and attribute { code, adminName } |
attributeFamily | AttributeFamily | The attribute family this product belongs to (not paginated) |
channels | ChannelCursorConnection | Channels this product is assigned to |
Variant & Configuration
| Relationship | Return Type | Description |
|---|---|---|
variants | ProductCursorConnection | Child variant products (for configurable products). Each variant is a full Product with its own id, name, sku, price, and attributeValues. |
superAttributes | AttributeCursorConnection | The attributes used for configurable options (e.g. Color, Size) |
parent | Product | Parent product (for variant products — returns the configurable parent) |
Product Type-Specific
| Relationship | Return Type | Description | Dropdown Example |
|---|---|---|---|
groupedProducts | ProductGroupedProductCursorConnection | Associated child products with qty, sortOrder, and associatedProduct details | "Get Grouped Product" |
bundleOptions | ProductBundleOptionCursorConnection | Bundle option groups with selectable products and quantities | — |
downloadableLinks | ProductDownloadableLinkCursorConnection | Downloadable links with price, formattedPrice, translation { title }, and sample info | "Get Downloadable Product with Samples" |
downloadableSamples | ProductDownloadableSampleCursorConnection | Product-level sample files with file, fileUrl, url, and translation { title } | "Get Downloadable Product with Samples" |
bookingProducts | BookingProductCursorConnection | Booking configuration with type, availableFrom, availableTo, qty, location, and type-specific slots | "Get Appointment/Rental/Default/Table/Event Booking Product" |
customizableOptions | ProductCustomizableOptionCursorConnection | Custom product options (e.g. engraving text, gift wrapping) | — |
Related & Recommended Products
| Relationship | Return Type | Description |
|---|---|---|
relatedProducts | ProductCursorConnection | Products marked as related — typically shown in a "Related Products" section on the product page |
upSells | ProductCursorConnection | Up-sell products — higher-value alternatives shown on the product page |
crossSells | ProductCursorConnection | Cross-sell products — complementary items shown during checkout or in the cart |
Reviews
| Relationship | Return Type | Description |
|---|---|---|
reviews | ProductReviewCursorConnection | All reviews for this product (all statuses) |
approvedReviews | ProductReviewCursorConnection | Only admin-approved reviews — use this for public-facing display |
Every relationship above is cursor-paginated and accepts first, last, before, and after — images(first: 5) returns only the first five images. Page through a large collection with the nested pageInfo { hasNextPage endCursor }.

