Skip to main content
The 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_url for fast rendering in lists without iterating arrays.
  • 🛒 Quick Add: Includes default variant data (price, stock, sku) at root level.
  • 🔍 Intelligence: Use the has_variants flag 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, or null when it has none) and review_count (0 when 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

Pass personalize: 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

Pass b2b: 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
A wholesale response is specific to one buyer, so it is not cached. Ordinary retail reads keep their caching unchanged. Filter by brand. Pass 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.
Each value must be a valid UUID. An id that matches nothing returns an empty 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
On a marketplace operator key the brands are aggregated across all active merchants; pass 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) and price_range (min/max using selling_price).
  • Variants Array: Clean array containing variant-specific attributes (color, size, SKU) and isolated media for that specific variation.
Where a colour is set, 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.
A multi-variant detail response (here shown for the “Nebula Ceramic Mug”, a 3-variant product) — root metadata plus aggregate 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.
These fields are also included in a store’s public catalog feed, so a catalog mirrored from one store into another preserves its SEO metadata.

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, or used. Defaults to new.
  • 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 no gtin.
  • 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_category and meta_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 of category_name, which is the store’s own taxonomy.
Every one of these is optional except 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.
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 the variants[] 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.
Supported Fields for Filtering:
  • Core: product_id, name, sku, description, thumbnail_url, media
  • Pricing: price, selling_price, sale_price, price_range
  • Inventory: stock, total_stock, last_restocked (last_restocked is 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
The merchant controls both the field names and how many exist, so render the array rather than reading fixed keys. See Custom Fields for the full picture — which records carry them, what each type looks like, and how to send values with an order. 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
An empty collection returns { "items": [] }.

Response Codes

All product endpoints are GET and accept both publishable and secret keys.