ProductsService class (accessed via client.products) reads a store’s catalog: products and their variants, filtering and pagination across them, product specifications, and the collections products are grouped into.
Validation & Rate Limits: Product IDs must be valid UUIDs — malformed IDs return
400 immediately. All endpoints are rate-limited per API key and, for a publishable key, per shopper network at the store; the limits grow with the store’s plan (see Core Concepts).Product identifier: every product object exposes both
id and product_id. They are the same value — use whichever fits your codebase.Response Structure Tiers
To optimize performance across different device types, the service implements three response tiers:Catalog Discovery
listProducts
Retrieve a paginated list of products. This method returns flat structures (no variants array) to keep payloads small.
- ⚡ Performance: 50-70% smaller than detail endpoints.
- 🖼️ Thumbnails: Use
thumbnail_urlfor fast rendering in lists without iterating arrays. - 🛒 Quick Add: Includes default variant data (
price,stock,sku) at root level. - 🔍 Intelligence: Use the
has_variantsflag to determine if the UI should show “View Options”. - ⭐ Ratings: Each item carries
average_rating(the mean of the product’s approved reviews, to one decimal place, ornullwhen it has none) andreview_count(0when none), so a grid can show a rating under each card without a review request per product. - ⏩ Pagination: Uses cursor-based navigation for stable, high-performance scrolling.
Lean by default. The list omits heavy fields a catalog grid rarely needs — the long-form
description, the SEO block (seo_title / seo_description / seo_keywords), raw attributes /
shipping_info, and the full media arrays — so grids stay fast. Get those on the detail calls
(getProduct / getProductBySlug), request them explicitly with fields (e.g.
fields: 'name,price,description,seo_title'), or pass full: true to return the complete object
for every row. thumbnail_url, price, stock, has_variants, the taxonomy fields and the
review rating (average_rating, review_count) are always present. The rating is on the list only;
the detail calls do not carry it, and listReviews returns the full summary for one product.Response
Personalized ordering
Passpersonalize: true together with a signed-in customer’s session token (the x-auth-token
header) and the page is ordered by how closely each product matches that shopper’s preferences,
with the default order as the tiebreak. Without a customer session — or for a shopper who has no
preference signal yet — the order is unchanged, so it is always safe to request.
Wholesale pricing for a signed-in buyer
Passb2b: true together with a wholesale buyer’s session token and each product is priced against
that buyer’s own agreement rather than at the shelf price, with the page narrowed to the range they
are allowed to order from. A request without a buyer credential — or from a customer who is not a
wholesale buyer on this store — returns the store’s standard listing at list prices and the full range,
unnarrowed. The request is not refused.
Each priced row carries moq, the smallest quantity that may be ordered, and price_source, which
says which arrangement set the price: assigned for a list assigned to that buyer, group for
their customer tier, default for the store’s standard wholesale list, and retail_fallback when
nothing wholesale was agreed for that line.
Response
brand (case-insensitive exact match) to build a brand landing page —
pair it with listBrands below to render a “shop by brand” row, then list the chosen brand’s products:
Filter by category and subcategory
category_id and subcategory_id both match a whole branch of the taxonomy rather than a single
node. A category matches products filed directly against it and products filed under any of its
subcategories, at any depth; a subcategory matches products filed against it and every nested
subcategory beneath it. A category page therefore returns the products of the branch as a shopper
understands it — a “Computers” category includes everything under “Laptops” without listing each
subcategory separately.
products array with a
200, not an error. The two filters can be combined, in which case a product must match both.
The subcategories of a category are available from GET /v1/subcategories?category_id=….
Several ids in one request. Both parameters accept multiple ids, in three forms:
Passing several ids to one request keeps a single pagination cursor valid across the combined set.
One request per category yields a separate cursor per response, and those cursors cannot be merged
into a coherent page 2 — so a landing page spanning several categories is built from one multi-id
request, not from several single-id requests stitched together.
listBrands
Return the catalog’s distinct brands, each with a product count, sorted by count (most products
first). Use it to build brand navigation — for example a “featured brands” row after the hero — then
pass a chosen brand to listProducts({ brand }).
Response
storeId
to scope to one merchant.
getProduct
Retrieve complete details for a single item. This method handles Multi-Variant products by returning a hierarchical structure that eliminates data redundancy and supports variant-aware media.
- Product-Level: Shared metadata at the root (name, brand, media gallery).
- Aggregate Data:
total_stock(sum of all variants) andprice_range(min/maxusingselling_price). - Variants Array: Clean array containing variant-specific attributes (color, size, SKU) and isolated media for that specific variation.
variant_attributes.color is its name and variant_attributes.color_hex the
matching #RRGGBB value, so a colour swatch renders from the response itself rather than from a
lookup table of colour names. Both are optional: a variant may carry a name with no hex, and one that
carries neither has no colour set.
price_range / total_stock and a clean variants[]
array, each with its own SKU, attributes, and isolated media:
Response
getProductBySlug
Retrieve a product using its SEO-friendly slug. Identical to getProduct in response structure but optimized for PDP routing.
SEO metadata
Every product carries optional SEO metadata for rendering search-engine-friendly product detail pages:seo_title— the<title>for the product page.seo_description— the meta description.seo_keywords— an array of keywords.
Channel and logistics fields
Alongside the merchandising fields, a product carries the identifiers and measurements that sales channels and shipping calculations need.condition— the condition the item is sold in:new,refurbished, orused. Defaults tonew.gtin— the manufacturer’s Global Trade Item Number (UPC, EAN, or ISBN). Sales channels match a listing against this to identify the product. It is distinct from the barcode a merchant scans in store, which may be an internal label and is never returned by this API.mpn— the manufacturer part number, which identifies items that carry nogtin.weight_grams— the shipped weight of the item, in grams.dimensions_cm— the packed dimensions in centimetres, as free text in the merchant’s own format. Parse it defensively rather than assuming a fixed shape.google_product_categoryandmeta_product_category— the product’s category in the Google Shopping and Meta commerce taxonomies. Each is set separately, because the two taxonomies do not share category names, and both are independent ofcategory_name, which is the store’s own taxonomy.
condition, so treat a null as “the merchant has not
supplied it” rather than as an error.
Response
condition, gtin, mpn, weight_grams and dimensions_cm describe an individual item, so
they belong to the variant — two sizes of one shirt carry different codes and weights.
google_product_category, meta_product_category and tags classify the listing as a whole and
belong to the product. All of them are returned on listProducts and on detail, including for a
product with several variants, and any of them can be named in fields.
📸 Media Gallery System
The media system supports a fully-functional, variant-aware gallery.Root-Level Media
thumbnail_url: Represents the primary image for the product. Perfect for simple grids.media: An array of objects containing all base-level images and videos.
Variant Media
Each variant in thevariants[] array can have its own media array. This allows you to show specific images when a user selects a particular variation (e.g., rotating the gallery to show the “Midnight Blue” model).
Media Object Structure:
🎨 Advanced Field Filtering
Tybrite supports powerful field selection to minimize bandwidth.Root-Level Filtering
Exclude large metadata objects by selecting only top-level fields.Nested Array Filtering
Use dot notation to select specific fields within nested arrays.- Core:
product_id,name,sku,description,thumbnail_url,media - Pricing:
price,selling_price,sale_price,price_range - Inventory:
stock,total_stock,last_restocked(last_restockedis not returned by default — request it explicitly) - Variants:
variants.sku,variants.selling_price,variants.media,variants.variant_attributes - Reviews (list only):
average_rating,review_count
Product Specifications
getProductSpecifications
Retrieve the latest published specifications for a single variant. Specifications are stored per
variant, so pass a variant id (e.g. a variant_id from getProduct().variants[]) — not a
product id. A product id returns 404.
Response
Returns
404 (“No specifications found for this product”) if the variant has no published
specification — or if you passed a product id instead of a variant id. To browse all specs across
the catalog (each tagged with its variant_id), use listProductSpecifications.getProductCustomFields
Retrieve the merchant’s own custom fields for a product. A merchant can define fields Galactic Core does
not — a care instruction, a country of origin, a fabric composition — and fill them per product.
Only fields the merchant published are returned. A custom field can hold a cost or an internal reference,
so a field is private unless it is explicitly marked public, and a private field is absent rather than
empty. A product with no published fields returns an empty array.
Response
field_type tells you the shape of value: multiselect is an array of strings, json,
dimensions and weight are objects, and the rest are scalars — a number field arrives as a number,
not as text. field_label is what the merchant calls the field and is the string to show; field_name
is stable across label edits and is the one to key off in code.
value is null when the merchant defined a field but has not filled it for this product, which is
distinct from the field not existing.listProductSpecifications
Browse specifications across the catalog rather than fetching one variant’s. Useful for building a
spec-driven filter (every value of “storage_type” in stock, say) without a request per variant.
Response
Each entry carries its own
variant_id, so a single pass over the list can be grouped by variant
without further lookups.
Collections
Curated groups of products a merchant highlights on their storefront — a “Featured”, “New Arrivals”, or “Summer Edit” row. Each collection can carry a banner image, which makes it a natural building block for an image-led homepage.listProductCollections
Response
image is the collection’s banner and the image to use on every viewport; image_mobile is an optional phone-sized crop. Render the mobile image on small screens when it is set and fall back to image otherwise — a <picture> element with a mobile <source> handles this cleanly. Either field is null when the merchant has not added artwork. video is an optional short video (MP4) for the same banner, null when none is set; image stays its poster and the fallback, so a storefront can play video where it supports it and show image otherwise.
getProductCollection
Fetch a single collection by id — the same shape listProductCollections returns for that entry,
so use it when you land directly on a collection page and have only the id from the URL. A
collection the merchant built from rules rather than by hand also carries those rules.
Response
rules describes how an automated or smart collection selects its products, and is null for a
collection the merchant curated by hand.
Returns 404 when no collection matches the id.
getProductCollectionItems
Response
{ "items": [] }.
Response Codes
All product endpoints areGET and accept both publishable and secret keys.

