Single Product
Returns the full PDP-ready document for a product — categories, channels, attribute family, images, videos, super-attributes (configurable parents), variants, bundle options, booking config, grouped members, downloadable links / samples, customizable options, related/up-sell/cross-sell products — all embedded inline. No follow-up requests are needed to render a complete product detail page.
Endpoint
GET /api/shop/products/{id}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. |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Product primary key |
Response
200 OK — single product object. The card-level fields (id, sku, type, name, price, …) are present, plus the embedded relations below.
Card-level fields
Same shape as items in Products — see that page for the field table. This includes the per-customer isInWishlist and isInCompare booleans.
Wishlist & compare flags:
isInWishlist(active channel) andisInComparetell you whether the signed-in customer already has this product in their wishlist / compare list (1= yes,0= no), so you can highlight the wishlist / compare icon on the product page without a separate lookup. Include the customer Bearer token alongside the storefront key — for guests both are0. REST returns1/0integers (over GraphQL the same flags come back as the strings"1"/"0").
Always-present extras (over the list)
| Field | Type | Description |
|---|---|---|
description | string | Full HTML description |
createdAt | string (ISO) | Creation timestamp |
updatedAt | string (ISO) | Last update timestamp |
isSaleable | boolean | Whether the product passes saleability checks (stock, status, …) |
attributeFamily | object | { id, code, name } |
Filterable attribute summary
The default-family product output includes top-level shortcuts for the common filterable attributes:
| Field | Type | Description |
|---|---|---|
color | object | null | { id, code, label } for the assigned color option |
size | object | null | Same shape, for size |
brand | object | null | Same shape, for brand |
The exact set depends on the active attribute family — these three are present for the default family.
Embedded relations (always present, may be empty [])
| Field | Type | Notes |
|---|---|---|
categories | array | Categories the product belongs to |
channels | array | Channels exposing this product ({ id, code, hostname, currencyCode, localeCode }) |
images | array | Image objects ({ id, type, path, productId, position, publicPath }) |
videos | array | Video objects |
superAttributes | array | Configurable type only — list of attributes used to build variants, with their options inlined |
variants | array | Configurable type only — child variant products, each carrying card-level fields |
bookingProducts | array | Booking type only — slot config with type (default/appointment/rental/event/table) and a type-specific slots block |
bundleOptions | array | Bundle type only — option groups with their member products inlined |
groupedProducts | array | Grouped type only — associated products |
downloadableLinks | array | Downloadable type only — purchasable links |
downloadableSamples | array | Downloadable type only — preview samples |
customizableOptions | array | Per-product custom inputs (text fields, file uploads, dropdowns added by the merchant) |
relatedProducts | array | "Customers also bought" cards |
upSells | array | "Upgrade to" cards |
crossSells | array | "Pairs well with" cards (shown in the cart/checkout) |
Empty
[]for product types that don't apply — asimpleproduct has novariants, abookingproduct has nobundleOptions, etc. Clients should treat these as "render only if non-empty".
What this endpoint deliberately omits
attributeValues— the raw EAV table is not returned. Use the typed fields (name,description,price,color, …) instead.- Reviews — fetched separately via the Product Reviews endpoint, paginated.
Sub-resource endpoints
Each embedded relation is also available as its own URL — useful when you only need one slice without re-fetching the entire PDP. These are tagged Product or Product Types in Swagger UI:
| URL | Returns |
|---|---|
GET /api/shop/products/{productId}/variants | Variants for a configurable product |
GET /api/shop/products/{productId}/booking-products | Booking config row(s) for a booking product |
GET /api/shop/booking-products/{id} | Single booking config (with type-specific slots) |
GET /api/shop/booking-slots?id={bp}&date=YYYY-MM-DD | Runtime slot availability — see Booking Slots |
Use Cases
- Render a full product detail page in one network round trip.
- Configurable variant picker: read
superAttributes[]for the dimensions,variants[]for the inventory of combinations. - Bundle builder: walk
bundleOptions[]for the selectable groups; each group has its member products inlined. - Determine product type at render time via
type(simple,configurable,bundle, …) andbookingType(default,appointment,rental,event,tablefor booking products).
Related Resources
- Products — paginated card-level list
- Search Products — full filter / sort / search reference
- Booking Slots — runtime availability for booking products
- Categories
- Attributes

