Product Catalog Storefront API Reference
Every operation of the storefront API at https://catalog.usethrottle.dev,
rendered from its OpenAPI document. Every route except the document itself takes a publishable key in
X-Catalog-Key.
Sending the key
A GET may send the key as ?key= instead of the
header, so a browser read needs no preflight. A browser, app or legacy key is accepted this way, never together with the header (that is a 400 INVALID_REQUEST): a server key in a
URL answers 403 KEY_NOT_ALLOWED_IN_URL, and a POST
always uses X-Catalog-Key. The customer token is never accepted in a URL; it
travels in X-Customer-Token. The SDK's suggest
never sends it, so suggestions from the SDK are list prices. See Keys and channels.
Browse
Product lists, filters and products.
GET /v1/storefront/products Publishable key
A page of products with filters, facets and sorting.
X-Catalog-Key · customer token optional
Implementation details
Operation listProducts.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
q | string | No | Full-text search. Length at most 200 |
category | string | No | A category handle; products of its children are included. |
collection | string | No | A collection handle. |
tag | string[] | No | A tag; repeat the parameter for several. |
featured | boolean | No | Only featured (true) or only other (false) products. |
handles | string[] | No | Product handles; repeat the parameter (commas are literal). |
skus | string[] | No | SKUs; repeat the parameter (commas are literal). |
year | integer | No | Vehicle year; the vehicle filter applies when make and model are set. |
make | string | No | Vehicle make (with model). |
model | string | No | Vehicle model (with make). |
submodel | string | No | Vehicle submodel (with make and model). |
engine | string | No | Vehicle engine (with make and model). |
sort | string | No | The order; absent, the store default. best_rated only while ratings show on lists.Values: relevance, featured, manual, title_asc, title_desc, price_asc, price_desc, newest, updated, best_rated |
limit | integer | No | Products per page. Value 1–100 |
page | integer | No | A page number (not with cursor). Value at least 1 |
cursor | string | No | page.nextCursor of the previous page (not with page). Length at most 1024 |
facets | string[] | No | true for every filter, or filter keys (comma-separated or repeated). |
fields | string[] | No | lite (default), full, or a comma list of top-level product keys. |
include | string[] | No | Opt-in parts, comma-separated or repeated: fitment, oemNumbers, supersessions, jsonLd, descriptionHtml. |
currency | string | No | An ISO 4217 currency the store has enabled; prices are answered in it. |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
filter.{key} | string[] | No | A selected value of the filter key (filter.color=Red); repeat for several values. A range filter takes one min..max value. The parameter name is a pattern: filter. followed by a filter key. |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
products | StorefrontListProduct[] | Yes | |
page | object | Yes | |
page.number | integer | Yes | Value at least 1 |
page.limit | integer | Yes | Value 1–100 |
page.total | integer | null | Yes | |
page.pageCount | integer | null | Yes | |
page.nextCursor | string | null | Yes | |
page.capped | true | No | |
filters | object[] | No | |
filters[].key | string | Yes | Length at least 1 |
filters[].label | string | Yes | |
filters[].display | string | Yes | Values: checkbox, swatch, range, boolean, dropdown |
filters[].values | object[] | Yes | Items at most 50 |
filters[].range | object | No | |
filters[].more | boolean | Yes | |
applied | object | Yes | |
applied.q | string | No | |
applied.category | string | No | |
applied.collection | string | No | |
applied.tags | string[] | No | |
applied.featured | boolean | No | |
applied.filters | object | Yes | |
applied.ignored | string[] | No | |
sort | string | Yes | Values: relevance, featured, manual, title_asc, title_desc, price_asc, price_desc, newest, updated, best_rated |
currency | string | null | Yes | |
locale | string | null | Yes | |
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
indexing | true | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/filters/{key}/values Publishable key
Every value of one filter for the current selection (the list's parameters).
X-Catalog-Key · no customer token
Implementation details
Operation listFilterValues.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
key | string | Yes | The filter key. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
q | string | No | Full-text search. Length at most 200 |
category | string | No | A category handle; products of its children are included. |
collection | string | No | A collection handle. |
tag | string[] | No | A tag; repeat the parameter for several. |
featured | boolean | No | Only featured (true) or only other (false) products. |
handles | string[] | No | Product handles; repeat the parameter (commas are literal). |
skus | string[] | No | SKUs; repeat the parameter (commas are literal). |
year | integer | No | Vehicle year; the vehicle filter applies when make and model are set. |
make | string | No | Vehicle make (with model). |
model | string | No | Vehicle model (with make). |
submodel | string | No | Vehicle submodel (with make and model). |
engine | string | No | Vehicle engine (with make and model). |
sort | string | No | The order; absent, the store default. best_rated only while ratings show on lists.Values: relevance, featured, manual, title_asc, title_desc, price_asc, price_desc, newest, updated, best_rated |
limit | integer | No | Products per page. Value 1–100 |
page | integer | No | A page number (not with cursor). Value at least 1 |
cursor | string | No | page.nextCursor of the previous page (not with page). Length at most 1024 |
facets | string[] | No | true for every filter, or filter keys (comma-separated or repeated). |
fields | string[] | No | lite (default), full, or a comma list of top-level product keys. |
include | string[] | No | Opt-in parts, comma-separated or repeated: fitment, oemNumbers, supersessions, jsonLd, descriptionHtml. |
currency | string | No | An ISO 4217 currency the store has enabled; prices are answered in it. |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
filter.{key} | string[] | No | A selected value of the filter key (filter.color=Red); repeat for several values. A range filter takes one min..max value. The parameter name is a pattern: filter. followed by a filter key. |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
key | string | Yes | Length at least 1 |
label | string | Yes | |
display | string | Yes | Values: checkbox, swatch, range, boolean, dropdown |
values | object[] | Yes | Items at most 1000 |
values[].value | string | Yes | |
values[].label | string | Yes | |
values[].count | integer | Yes | |
values[].selected | boolean | Yes | |
values[].swatch | object | object | No | |
range | object | No | |
range.min | number | Yes | |
range.max | number | Yes | |
range.selectedMin | number | No | |
range.selectedMax | number | No | |
more | boolean | Yes | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/products/{handle} Publishable key
One product. With fields, include, currency or locale the full product; without, the legacy answer. An old handle answers { redirectTo }.
X-Catalog-Key · customer token optional
Implementation details
Operation getProduct.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The product handle. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
fields | string[] | No | Any value switches to the full product (the page is always full). |
include | string[] | No | Opt-in parts, comma-separated or repeated: fitment, oemNumbers, supersessions, jsonLd, descriptionHtml. |
currency | string | No | An ISO 4217 currency the store has enabled; prices are answered in it. |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. One of 2 answer shapes. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
product | object | No | |
product.handle | string | No | Length at least 1 |
product.title | string | null | No | |
product.description | string | null | No | |
product.brand | string | null | No | |
product.productType | string | null | No | |
product.googleCategory | string | null | No | |
product.link | string | null | No | |
product.images | object[] | No | |
product.priceRange | object | null | No | |
product.availability | string | null | No | |
product.variants | object[] | No | |
product.shortDescription | string | null | No | |
product.seoTitle | string | null | No | |
product.seoDescription | string | null | No | |
product.tags | string[] | No | |
product.categories | object[] | No | |
product.featured | boolean | No | |
product.draft | boolean | No | |
product.descriptionHtml | string | null | No | |
product.seo | object | No | |
product.jsonLd | object | No | |
product.options | object[] | No | |
product.breadcrumbs | object[] | No | |
product.lowStock | boolean | No | |
product.purchasable | boolean | No | |
product.availableInCurrency | boolean | No | |
product.rating | object | No | |
locale | string | null | No | |
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
redirectTo | string | No | Length 1–255 |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/products/{handle}/related Publishable key
Products related to one product (the store's picks, then the related mode).
X-Catalog-Key · customer token optional
Implementation details
Operation listRelatedProducts.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The product handle. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
limit | integer | No | Products to answer. Value 1–24 |
fields | string[] | No | lite (default), full, or a comma list of top-level product keys. |
currency | string | No | An ISO 4217 currency the store has enabled; prices are answered in it. |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
products | StorefrontListProduct[] | Yes | Items at most 24 |
locale | string | null | No | |
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
catalog.products.related()
The SDK sends the key, the customer token and the idempotency key for you.
Taxonomy
Categories, tags and collections.
GET /v1/storefront/categories Publishable key
The category tree.
X-Catalog-Key · no customer token
Implementation details
Operation getCategoryTree.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
depth | integer | No | Levels of the tree to answer. Value 1–10 |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
categories | StorefrontCategoryNode[] | Yes | |
locale | string | null | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
catalog.categories.tree()
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/categories/{handle} Publishable key
One category with its breadcrumb and children.
X-Catalog-Key · no customer token
Implementation details
Operation getCategory.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The category handle. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
category | object | Yes | |
category.id | string | Yes | Length at least 1 |
category.handle | string | Yes | Length at least 1 |
category.name | string | Yes | Length at least 1 |
category.description | string | null | Yes | |
category.seoTitle | string | null | Yes | |
category.productCount | integer | Yes | |
breadcrumbs | object[] | Yes | |
breadcrumbs[].handle | string | Yes | Length at least 1 |
breadcrumbs[].name | string | Yes | Length at least 1 |
children | StorefrontCategoryNode[] | Yes | |
locale | string | null | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/tags Publishable key
Product tags with counts.
X-Catalog-Key · no customer token
Implementation details
Operation listTags.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
q | string | No | Tags that start with this text. Length at most 100 |
limit | integer | No | Tags to answer. Value 1–200 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
tags | object[] | Yes | |
tags[].tag | string | Yes | Length at least 1 |
tags[].productCount | integer | Yes | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/collections Publishable key
A page of published collections.
X-Catalog-Key · no customer token
Implementation details
Operation listCollections.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
limit | integer | No | Collections per page. Value 1–100 |
cursor | string | No | nextCursor of the previous page. Length at most 1024 |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
collections | object[] | Yes | |
collections[].handle | string | Yes | Length at least 1 |
collections[].title | string | Yes | |
collections[].kind | string | Yes | Values: manual, rule |
collections[].image | object | null | Yes | |
collections[].productCount | integer | Yes | |
nextCursor | string | null | Yes | |
locale | string | null | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
catalog.collections.list()
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/collections/{handle} Publishable key
One collection. An old handle answers { redirectTo }.
X-Catalog-Key · no customer token
Implementation details
Operation getCollection.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The collection handle. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. One of 2 answer shapes. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
collection | object | No | |
collection.handle | string | No | Length at least 1 |
collection.title | string | No | |
collection.description | string | null | No | |
collection.descriptionHtml | string | null | No | |
collection.image | object | null | No | |
collection.seo | object | No | |
collection.kind | string | No | Values: manual, rule |
collection.defaultSort | string | No | Values: featured, manual, title_asc, title_desc, price_asc, price_desc, newest, updated |
locale | string | null | No | |
redirectTo | string | No | Length 1–255 |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
catalog.collections.get()
The SDK sends the key, the customer token and the idempotency key for you.
Search
Search-as-you-type suggestions.
GET /v1/storefront/suggest Publishable key
Search-as-you-type: products, categories, collections and queries.
X-Catalog-Key · customer token optional
Implementation details
Operation suggest.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
q | string | Yes | What the shopper typed. Length 2–100 |
limit | integer | No | Products to answer. Value 1–8 |
currency | string | No | An ISO 4217 currency the store has enabled; prices are answered in it. |
locale | string | No | The answer language (BCP 47 style, e.g. fr or fr-CA); the answer names the locale it used. Length at most 35 |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
products | object[] | Yes | Items at most 8 |
products[].handle | string | Yes | Length at least 1 |
products[].title | string | null | Yes | |
products[].images | object[] | Yes | Items at most 2 |
products[].priceRange | object | null | Yes | |
products[].availability | string | null | Yes | |
categories | object[] | Yes | Items at most 5 |
categories[].handle | string | Yes | Length at least 1 |
categories[].name | string | Yes | Length at least 1 |
categories[].productCount | integer | Yes | |
brands | object[] | Yes | Items at most 5 |
brands[].name | string | Yes | Length at least 1 |
brands[].productCount | integer | Yes | |
tags | object[] | Yes | Items at most 5 |
tags[].tag | string | Yes | Length at least 1 |
tags[].productCount | integer | Yes | |
collections | object[] | Yes | Items at most 5 |
collections[].handle | string | Yes | Length at least 1 |
collections[].title | string | Yes | |
collections[].productCount | integer | Yes | |
locale | string | null | No | |
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
Carts
Cart checks and hosted carts in Throttle.
POST /v1/storefront/carts/check Publishable key
Prices and checks cart lines without creating a cart.
X-Catalog-Key · customer token optional
Implementation details
Operation checkCart. The JSON request body is required.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
Request body
| Field | Type | Required | Description |
|---|
items | object[] | Yes | Items 1–50 |
items[].sku | string | Yes | Length 1–255 |
items[].quantity | integer | Yes | Value 1–10000 |
currency | string | No | |
Responses
200 OK.
Response fields
| Field | Type | Required | Description |
|---|
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
items | object[] | Yes | |
items[].sku | string | Yes | |
items[].ok | boolean | Yes | |
items[].code | string | No | Values: NOT_FOUND, NOT_PURCHASABLE, OUT_OF_STOCK, QUANTITY_UNAVAILABLE, BELOW_MIN, ABOVE_MAX, NO_PRICE_IN_CURRENCY, PRICE_SOURCE_MISMATCH |
items[].unitPriceMinor | integer | null | Yes | |
items[].currency | string | null | Yes | |
items[].maxQuantity | integer | No | |
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
413 Request body too large.
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
POST /v1/storefront/carts Publishable key
Creates a Throttle cart from catalog lines and opens its hosted cart session.
X-Catalog-Key · customer token optional
Implementation details
Operation createCart. The JSON request body is required.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
Idempotency-Key | string | No | A retry with the same key answers the first request again instead of repeating it. Length 1–200 |
Request body
| Field | Type | Required | Description |
|---|
items | object[] | Yes | Items 1–50 |
items[].sku | string | Yes | Length 1–255 |
items[].quantity | integer | Yes | Value 1–10000 |
currency | string | No | |
locale | string | No | Length at most 35 |
returnUrl | string | No | Where the hosted checkout sends the shopper after paying. An absolute https URL on one of the store's allowed return websites (Checkout settings). Length at most 2048 |
cancelUrl | string | No | Where the hosted cart's cancel link goes. An absolute https URL on one of the store's allowed return websites (Checkout settings). Length at most 2048 |
storefrontUrl | string | No | The hosted cart's "Continue shopping" link. An absolute https URL on one of the store's allowed return websites (Checkout settings). Length at most 2048 |
Responses
201 Created.
Response fields
| Field | Type | Required | Description |
|---|
priceContext | string | No | Values: anonymous, customer, email_unverified, anonymous_fallback |
sessionId | string | Yes | |
cartUrl | string | Yes | |
expiresAt | string | Yes | |
cart | object | Yes | |
cart.lines | object[] | Yes | |
cart.currency | string | Yes | |
cart.subtotalMinor | integer | Yes | |
returnUrlApplied | boolean | No | |
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
409 Conflict with the store setup or an earlier request.
413 Request body too large.
422 The request is well formed but cannot be done (items names refused lines).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
502 Throttle refused the request (throttleCode).
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
Reviews
Product reviews.
GET /v1/storefront/products/{handle}/reviews Publishable key
A page of a product's published reviews with its rating summary.
X-Catalog-Key · no customer token
Implementation details
Operation listReviews.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The product handle. Length at least 1 |
Query parameters
| Field | Type | Required | Description |
|---|
sort | string | No | The order. Values: newest, highest, lowest |
rating | integer | No | Only reviews with this rating. Value 1–5 |
limit | integer | No | Reviews per page. Value 1–50 |
cursor | string | No | nextCursor of the previous page. Length at most 1024 |
locale | string | No | Checked and ignored: reviews are answered as written. Length at most 35 |
Responses
200 OK. One of 2 answer shapes. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
summary | object | No | |
summary.average | number | null | No | |
summary.count | integer | No | |
summary.histogram | object | No | |
reviews | object[] | No | |
reviews[].id | string | No | Length at least 1 |
reviews[].rating | integer | No | Value 1–5 |
reviews[].title | string | null | No | |
reviews[].body | string | No | |
reviews[].displayName | string | No | |
reviews[].verified | boolean | No | |
reviews[].imported | boolean | No | |
reviews[].createdAt | string | No | |
reviews[].reply | object | null | No | |
nextCursor | string | null | No | |
redirectTo | string | No | Length at least 1 |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
POST /v1/storefront/products/{handle}/reviews Customer token
Submits a review as the signed-in shopper.
X-Catalog-Key · customer token required
Implementation details
Operation submitReview. The JSON request body is required.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | Yes | The signed-in shopper's Throttle access token. Length 1–4096 |
Idempotency-Key | string | No | A retry with the same key answers the first request again instead of repeating it. Length 1–200 |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The product handle. Length at least 1 |
Request body
| Field | Type | Required | Description |
|---|
rating | integer | Yes | Value 1–5 |
title | string | null | No | |
body | string | Yes | |
displayName | string | Yes | Length 1–120 |
Responses
201 Created.
Response fields
| Field | Type | Required | Description |
|---|
review | object | Yes | |
review.id | string | Yes | Length at least 1 |
review.status | string | Yes | Values: pending, approved |
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
409 Conflict with the store setup or an earlier request.
413 Request body too large.
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
The SDK sends the key, the customer token and the idempotency key for you.
GET /v1/storefront/products/{handle}/reviews/eligibility Publishable key
Whether the signed-in shopper may review the product, and why not.
X-Catalog-Key · customer token optional
Implementation details
Operation getReviewEligibility.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
X-Customer-Token | string | No | The signed-in shopper's Throttle access token: customer prices and identity. Without it the answer is anonymous. Length 1–4096 |
Path parameters
| Field | Type | Required | Description |
|---|
handle | string | Yes | The product handle. Length at least 1 |
Responses
200 OK.
Response fields
| Field | Type | Required | Description |
|---|
canReview | boolean | Yes | |
reason | string | No | Values: reviews_disabled, not_signed_in, email_not_verified, already_reviewed, not_verified_buyer |
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
SDK coverage
@usethrottle/catalog · Browsers and Node.js 20+
catalog.reviews.eligibility()
The SDK sends the key, the customer token and the idempotency key for you.
Legacy
Routes kept for stores built before the storefront API.
GET /v1/storefront/search Publishable key
Legacy search (before the Part 2 list). Use listProducts.
X-Catalog-Key · no customer token
Implementation details
Operation legacySearch.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
q | string | No | Full-text search. Length at most 200 |
category | string | No | A Google product category. |
collection | string | No | A category handle. |
featured | boolean | No | Only featured or only other products. |
sort | string | No | The order. Values: relevance, title, price_asc, price_desc, updated |
cursor | string | No | nextCursor of the previous page. |
brand | string[] | No | Brands, comma-separated or repeated. |
productType | string[] | No | Product types, comma-separated or repeated. |
availability | string[] | No | Availabilities, comma-separated or repeated. |
facets | string[] | No | brand and/or productType, comma-separated or repeated. |
priceMin | integer | No | Lowest price in minor units. |
priceMax | integer | No | Highest price in minor units. |
limit | integer | No | Products per page. Value 1–100 |
year | integer | No | Vehicle year. |
make | string | No | Vehicle make. |
model | string | No | Vehicle model. |
submodel | string | No | Vehicle submodel. |
engine | string | No | Vehicle engine. |
Responses
200 OK. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
products | object[] | Yes | |
products[].handle | string | Yes | Length at least 1 |
products[].title | string | null | Yes | |
products[].description | string | null | Yes | |
products[].brand | string | null | Yes | |
products[].productType | string | null | Yes | |
products[].googleCategory | string | null | Yes | |
products[].link | string | null | Yes | |
products[].images | object[] | Yes | |
products[].priceRange | object | null | Yes | |
products[].availability | string | null | Yes | |
products[].variants | object[] | Yes | |
products[].shortDescription | string | null | No | |
products[].seoTitle | string | null | No | |
products[].seoDescription | string | null | No | |
products[].tags | string[] | No | |
products[].categories | object[] | No | |
products[].featured | boolean | No | |
products[].draft | boolean | No | |
products[].descriptionHtml | string | null | No | |
products[].seo | object | No | |
products[].jsonLd | object | No | |
nextCursor | string | null | Yes | |
facets | object | Yes | |
facets.brand | object[] | No | |
facets.productType | object[] | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
GET /v1/storefront/vehicles Publishable key
The vehicle picker: years, then makes for a year, models for a make, then submodels and engines.
X-Catalog-Key · no customer token
Implementation details
Operation listVehicles.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
If-None-Match | string | No | An ETag of an earlier answer: 304 when it still matches. |
Query parameters
| Field | Type | Required | Description |
|---|
year | integer | No | Vehicle year. |
make | string | No | Vehicle make. |
model | string | No | Vehicle model. |
Responses
200 OK. One of 4 answer shapes. Headers: ETag, Server-Timing.
Response fields
| Field | Type | Required | Description |
|---|
years | integer[] | No | |
makes | string[] | No | |
models | string[] | No | |
submodels | string[] | No | |
engines | string[] | No | |
304 Not modified: the answer still matches If-None-Match. Headers: ETag.
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
POST /v1/storefront/checkout Publishable key
Legacy checkout: a Throttle checkout session from catalog lines. Use createCart.
X-Catalog-Key · no customer token
Implementation details
Operation legacyCheckout. The JSON request body is required.
Headers
| Field | Type | Required | Description |
|---|
X-Catalog-Key | string | Yes | A publishable catalog key (pc_pk_…). |
Idempotency-Key | string | No | A retry with the same key answers the first request again instead of repeating it. Length 1–200 |
Request body
| Field | Type | Required | Description |
|---|
items | object[] | Yes | Items 1–50 |
items[].sku | string | Yes | Length 1–255 |
items[].quantity | integer | Yes | Value 1–10000 |
returnUrl | string | Yes | Length at most 2048 |
cancelUrl | string | Yes | Length at most 2048 |
customerEmail | string | No | Length at most 320 |
Responses
200 OK.
Response fields
| Field | Type | Required | Description |
|---|
checkoutUrl | string | Yes | |
sessionId | string | Yes | |
expiresAt | string | null | Yes | |
cartId | string | Yes | |
currency | string | Yes | |
lines | object[] | Yes | |
lines[].sku | string | Yes | |
lines[].quantity | integer | Yes | |
lines[].unitPriceMinor | integer | Yes | |
replayed | true | No | |
400 Invalid request: an unknown or malformed parameter or body (issues names each).
401 Missing or unknown key (AUTHENTICATION_FAILED), or an invalid customer token (CUSTOMER_TOKEN_INVALID).
403 Refused for this key or shopper (ORIGIN_NOT_ALLOWED, SERVER_KEY_IN_BROWSER, KEY_NOT_ALLOWED_IN_URL, review eligibility codes).
409 Conflict with the store setup or an earlier request.
413 Request body too large.
422 The request is well formed but cannot be done (items names refused lines).
429 Rate limited: retry after Retry-After seconds. Headers: Retry-After.
502 Throttle refused the request (throttleCode).
503 Temporarily unavailable: retry after Retry-After seconds when present. Headers: Retry-After.
Error codes
Every error answers the same envelope, with a stable error.code. These
are all the codes the API returns, with their HTTP statuses and whether a retry can succeed.