API-Referenz-Navigation
Storefront Collections
StorefrontStorefront Collections groups 4 operations on the storefront tier.
Storefront tier. Reachable anonymously; a public vnstss_ token may be sent to identify the storefront.
/api/{version}/collections
vnstss_ token may be sent to identify the storefront.Antworten
curl -X GET \
'https://<your-shop-domain>/api/2026-04-01/collections' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer vnstss_<token>'{
"collections": [
{
"id": "00000000-0000-0000-0000-000000000000",
"handle": "string",
"title": "string",
"body_html": "string",
"image": {
"id": "00000000-0000-0000-0000-000000000000",
"src": "string",
"preview_src": "string",
"alt": "string",
"position": 1,
"width": 1,
"height": 1
},
"products_count": 1,
"sort_order": "string",
"meta_title": "string",
"meta_description": "string",
"custom_fields": [
{}
]
}
]
}/api/{version}/collections/{id}
vnstss_ token may be sent to identify the storefront.Pfad-Parameter
| Name | Typ | Beschreibung |
|---|---|---|
| id erforderlich | string (uuid) |
Antworten
- 200StorefrontCollectionResponseOK
- 404ApiErrorResponseNot Found
curl -X GET \
'https://<your-shop-domain>/api/2026-04-01/collections/<id>' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer vnstss_<token>'{
"collection": {
"id": "00000000-0000-0000-0000-000000000000",
"handle": "string",
"title": "string",
"body_html": "string",
"image": {
"id": "00000000-0000-0000-0000-000000000000",
"src": "string",
"preview_src": "string",
"alt": "string",
"position": 1,
"width": 1,
"height": 1
},
"products_count": 1,
"sort_order": "string",
"meta_title": "string",
"meta_description": "string",
"custom_fields": [
{
"key": "string",
"label": "string",
"value": "string",
"type": "string"
}
]
}
}/api/{version}/collections/{id}/products
vnstss_ token may be sent to identify the storefront.Pfad-Parameter
| Name | Typ | Beschreibung |
|---|---|---|
| id erforderlich | string (uuid) |
Query-Parameter
| Name | Typ | Beschreibung |
|---|---|---|
| limit optional | integer (int32) | Page size. Clamped to 1..250 by the handler. |
| page_info optional | string | Opaque cursor. When present, filter params must match those that produced the cursor. |
| q optional | string | Free-text search within the collection. |
| vendor optional | string (uuid) | Manufacturer (vendor) filter. |
| order optional | string | Sort spec, e.g. |
| color_id optional | string | Colour facet ids ( |
| region_id optional | string | Region facet ids. |
| year_id optional | string | Vintage facet ids. |
| country_id optional | string | Country facet ids. |
| size_id optional | string | Bottle-size facet ids. |
| category_id optional | string | Category facet ids. AND'd: a product must sit in every category passed. |
| custom_field_id optional | string | Custom-field option ids ( |
| price_min optional | number (double) | Lower bound on the gross price, in the request's active currency. |
| price_max optional | number (double) | Upper bound on the gross price, in the request's active currency. |
| available optional | boolean |
|
| on_sale optional | boolean |
|
| include optional | string | Comma-separated extras to embed in the response. |
| IncludeFacets optional | boolean | Whether |
Antworten
- 200StorefrontProductListResponseOK
- 404ApiErrorResponseNot Found
- 422ApiErrorResponseUnprocessable Content
curl -X GET \
'https://<your-shop-domain>/api/2026-04-01/collections/<id>/products' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer vnstss_<token>'{
"products": [
{
"id": "00000000-0000-0000-0000-000000000000",
"handle": "string",
"title": "string",
"body_html": "string",
"image": "string",
"available": true,
"currency": "string",
"price_min": 1,
"price_max": 1,
"variants_count": 1,
"manufacturer": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "string",
"logo_url": "string"
},
"flag": {
"name": "string",
"color": "string"
},
"rating": 1,
"rating_count": 1,
"custom_fields": [
{}
],
"variants": [
{}
]
}
],
"facets": [
{
"key": "string",
"values": [
{}
]
}
],
"price_range": {
"min": 1,
"max": 1,
"currency": "string"
}
}/api/{version}/collections/{id}/facets
vnstss_ token may be sent to identify the storefront.Pfad-Parameter
| Name | Typ | Beschreibung |
|---|---|---|
| id erforderlich | string (uuid) |
Query-Parameter
| Name | Typ | Beschreibung |
|---|---|---|
| q optional | string | Free-text search. |
| vendor optional | string (uuid) | Manufacturer (vendor) filter — the |
| color_id optional | string | Colour facet ids ( |
| region_id optional | string | Region facet ids. |
| year_id optional | string | Vintage facet ids. |
| country_id optional | string | Country facet ids. |
| size_id optional | string | Bottle-size facet ids. |
| category_id optional | string | Category facet ids. AND'd: a product must sit in every category passed. |
| custom_field_id optional | string | Custom-field option ids ( |
| price_min optional | number (double) | Lower bound on the gross price, in the request's active currency. |
| price_max optional | number (double) | Upper bound on the gross price, in the request's active currency. |
| available optional | boolean |
|
| on_sale optional | boolean |
|
| include optional | string | Comma-separated extras to embed in the response. |
| IncludeFacets optional | boolean | Whether |
Antworten
- 200StorefrontFacetsResponseOK
- 404ApiErrorResponseNot Found
curl -X GET \
'https://<your-shop-domain>/api/2026-04-01/collections/<id>/facets' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer vnstss_<token>'{
"facets": [
{
"key": "string",
"values": [
{}
]
}
],
"price_range": {
"min": 1,
"max": 1,
"currency": "string"
}
}Schemas
ApiErrorResponse
The error envelope every non-2xx response from this API uses. Documentation shape: actions build it as an anonymous object, so this type exists to give the OpenAPI document a schema to point at.
errorsstringnullableHuman-readable description of what went wrong, e.g.
Not Found,Invalid page_info.codestringnullableMachine-readable error code. Only a few endpoints (checkout) emit one; omitted everywhere else.
StorefrontCollectionDto
Storefront representation of a published collection. body_html, meta_* and
custom_fields are only present on single-collection reads. Text is returned in the request's
active language, falling back to the collection's stored default text.
idstring (uuid)handlestringnullabletitlestringnullablebody_htmlstringnullableimageStorefrontImageDtoproducts_countinteger (int32)sort_orderstringnullablemeta_titlestringnullablemeta_descriptionstringnullableTenant-defined attributes of the collection; empty when none are set.
StorefrontCollectionListResponse
Envelope returned by GET /collections.
Every published collection. Always present; an empty array when the tenant has none.
StorefrontCollectionResponse
Envelope returned by GET /collections/{id}.
collectionStorefrontCollectionDto
StorefrontCustomFieldDto
Storefront custom field: a tenant-defined attribute (key, localized label, value, kind).
keystringnullablelabelstringnullablevaluestringnullabletypestringnullable
StorefrontFacetDto
Storefront filter facets: one entry per dimension (manufacturers, categories, colors, sizes, years,
countries, regions, custom_fields), each with its selectable values and product counts. Drives a
faceted-search / filter sidebar, mirroring ShopController's filters.
keystringnullableDimension key. One of a closed set, always emitted in this order:
manufacturers,categories,colors,sizes,years,countries,regions,custom_fields. No key is guaranteed to be present. A dimension is emitted only when at least one of its values has a non-zero product count for the current filters, so the key set is data-dependent — it varies by tenant, by language and by the filters on the request. Treat a missing key as "this dimension has nothing to offer here", not as an error, and never hard-code the key set observed on one tenant. Conversely, no key outside the eight above is ever returned.custom_fieldsis the catch-all for tenant-defined attributes: every configured custom field's options are flattened into this one dimension rather than getting a key of their own. On a wine tenant grape variety arrives here, alongside anything else the tenant has configured. Use each value'snamefor display and itsidas thecustom_field_idfilter token; there is no per-field grouping in the response.The selectable values for this dimension. Never empty — a dimension with no matching values is omitted from the response instead. Values whose count would be zero are dropped.
StorefrontFacetRefDto
One facet value: the id to filter by and its localized label. name is null while the tenant's
periodically-rebuilt filter snapshot doesn't yet carry the id — membership is still reported.
idstring (uuid)namestringnullable
StorefrontFacetsResponse
Envelope returned by GET /products/facets and GET /collections/{id}/facets, and by the
facets member of Cloudwawi.Shop.Api.V2026_04_01.Storefront.StorefrontProductListResponse.
One entry per facet dimension that has at least one matching value. See Cloudwawi.Shop.Api.V2026_04_01.Storefront.StorefrontFacetDto.Key for the closed set of keys and which of them are data-dependent. Always present; an empty array when the tenant has no filters configured or nothing matches.
price_rangeStorefrontPriceRangeDto
StorefrontFacetValueDto
One selectable facet value: filter token id, localized name, matching product count.
idstringnullableFilter token to send back, as a string (GUIDs are rendered in their usual dashed form). Which query parameter it belongs to follows from the facet key:
categories→category_id,colors→color_id,sizes→size_id,years→year_id,countries→country_id,regions→region_id,custom_fields→custom_field_id,manufacturers→vendor.namestringnullableDisplay label in the request's language; may be
nullwhen the tenant left it untranslated.valuestringnullableRaw value for custom-field options;
nullfor entity-backed facets.countinteger (int32)Number of products that would match if this value were selected. Always greater than zero. Counts are self-excluding within a dimension: for a dimension the caller has already filtered on, the counts ignore that dimension's own selection, so the other options in the same list stay clickable.
StorefrontFlagDto
Storefront product badge/flag: display name and CSS colour.
namestringnullablecolorstringnullable
StorefrontImageDto
Storefront representation of a product image. An image is an object (id, src, alt,
position, width, height) rather than a bare URL, so clients get the gallery order,
accessibility text, and intrinsic dimensions.
idstring (uuid)srcstringnullablepreview_srcstringnullablealtstringnullablepositioninteger (int32)widthinteger (int32)heightinteger (int32)
StorefrontManufacturerDto
Storefront manufacturer (vendor): id, display name, logo URL.
idstring (uuid)namestringnullablelogo_urlstringnullable
StorefrontPriceRangeDto
The price range of a filtered catalog: what a price slider's ends should be. Money is in the request's
active currency, quoted gross — the same basis as price_min/price_max take.
Kept out of the facet list on purpose. A facet value is an id with a count, and a price range is
neither, so a client that renders facets generically would have had to special-case it anyway.
minnumber (double)Cheapest gross price in the matching set.
maxnumber (double)Dearest gross price in the matching set.
currencystringnullableISO code the two figures are in.
StorefrontProductDto
Storefront representation of a catalog product. This is the list projection: it carries the product's
gross retail price range (price_min/price_max in currency) and variant count so a
listing/collection card can show a price range and an "N options" badge, mirroring a Shopify storefront
listing. The full variant list is served by the detail read and /{id}/variants.
idstring (uuid)handlestringnullabletitlestringnullablebody_htmlstringnullableimagestringnullableavailablebooleancurrencystringnullableprice_minnumber (double)Lowest variant gross price;
0when the product has no priced variant.price_maxnumber (double)Highest variant gross price;
0when the product has no priced variant.variants_countinteger (int32)Number of active, published variants.
manufacturerStorefrontManufacturerDtoratingnumber (double)Average approved rating (0 when unrated).
rating_countinteger (int32)Number of approved ratings.
Tenant-defined custom attributes for the representative variant.
The product's variants (list-level view from the catalog index). Tax rate, alcohol volume and option group are not carried by the index and are left at their defaults here; the single-product detail read returns the fully-resolved variants. For a text search only matching variants appear — see Cloudwawi.Shop.Api.V2026_04_01.Storefront.StorefrontProductDto.VariantsCount for the true total.
StorefrontProductListResponse
Envelope returned by GET /products and GET /collections/{id}/products.
One page of products, in the order requested by order. Paging is cursored: when more products
match, the response carries a Link header of the form
<https://…?…&limit=50&page_info=…>; rel="next". Follow that URL verbatim — the cursor
embeds a fingerprint of the filters that produced the page, and a request whose filters no longer match
is rejected with 422. There is no total count and no last page link.
The page of products. Always present; an empty array when nothing matches.
Filter facets for this result set — identical to what the matching
/facetsendpoint returns for the same filters. Present only when the request passedinclude=facets; the property is omitted entirely otherwise (it is nevernullon the wire).price_rangeStorefrontPriceRangeDto
StorefrontQuantityRuleDto
Storefront variant quantity rule: minimum, optional maximum, and increment (step).
minnumber (double)maxnumber (double)nullableincrementnumber (double)
StorefrontVariantDto
Storefront representation of a product variant, including the product attributes the storefront page
renders. Money fields are in the enclosing response's currency — Cloudwawi.Shop.Api.V2026_04_01.Storefront.StorefrontProductDetailDto.Currency
on the detail read, the sibling currency field on the /{id}/variants envelope.
idstring (uuid)product_idstring (uuid)handlestringnullabletitlestringnullableskustringnullableoption_groupstringnullablepricenumber (double)Display price (gross, tax included).
net_pricenumber (double)compare_at_pricenumber (double)Pre-discount price when on offer;
0otherwise.tax_ratenumber (double)availablebooleaninventory_quantitynumber (double)descriptionstringnullabledescription_additionalstringnullableyearstringnullablesizestringnullableareastringnullablecountrystringnullablealcohol_volumenumber (double)nullablequantity_ruleStorefrontQuantityRuleDtoTenant-defined custom attributes for this variant.
factsheet_urlstringnullableRelative URL of the generated variant factsheet PDF.
StorefrontVariantFacetsDto
A variant's facet membership. Each entry pairs the filter token a client sends back with its localized label, so a card can render attribute chips and a client can filter in-memory without a second call.
regionStorefrontFacetRefDtovintageStorefrontFacetRefDtoTenant-defined dropdown options (grape variety, for tenants that model it). Each carries the owning field's
field_keyso a client can select the field it cares about.
StorefrontVariantOptionDto
A selected tenant-defined option, qualified by the custom field that owns it.
field_keystringnullableStable machine key of the owning custom field (falls back to its numeric code).
field_labelstringnullableLocalized display name of the owning custom field.
idstring (uuid)namestringnullable
