ProductsService class (accessed via client.products) is the core discovery engine. It provides high-performance access to your catalog with advanced filtering, hierarchical variant structures, and a unified media gallery system.
Validation & Rate Limits: Product IDs must be valid UUIDs — malformed IDs return
400 immediately. All endpoints are rate-limited (publishable key: 1,000 requests/hr per IP; secret key: 10,000 requests/hr per key).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”. - ⏩ 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 and the taxonomy fields are always
present.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.
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:
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.
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.
📸 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
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.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.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.
Response Codes
All product endpoints areGET and accept both publishable and secret keys.

