---
title: "List product catalog with inventory"
method: POST
path: "/products/catalog"
tags: ["Products"]
---

# List product catalog with inventory

`POST /products/catalog`

## Request

- Base URL: `https://api.reacherapp.com/public/v1`
- URL: `https://api.reacherapp.com/public/v1/products/catalog`
- Auth: API key in header `x-api-key` and API key in header `x-shop-id`

The shop's merchandising catalog with current stock — for syncing products into an external CRM or ordering system. Sourced from TikTok's product catalog (refreshed roughly every 6 hours), NOT the affiliate performance data in POST /products/list.

Each product carries its product-level inventory (`total_inventory`, `sku_count`, `out_of_stock_sku_count`) and, by default, a nested `skus[]` array with per-SKU stock and variant attributes. Set `include_skus=false` for a lighter product-only payload.

All money is reported as integer minor currency units (cents) in the product's `currency`. Prices and stock are passed through exactly as TikTok reports them: product-level `total_inventory` and per-SKU `inventory` can legitimately differ during a sync, so do not assume `total_inventory` equals the sum of SKU inventories. There is no warehouse-level stock breakdown — inventory exists only at the product and SKU grain.

For incremental syncs, pass `updated_since` and key off each row's `updated_at`. Soft-deleted products are excluded.

## Request body

- ProductCatalogRequest: POST /products/catalog request body. Merchandising catalog + current inventory (no date range), sourced from product_catalog / product_catalog_sku. Distinct from ProductsListRequest, which is affiliate performance over a date window.
  - `page` integer
  - `page_size` integer
  - `sort_by` 'title' | 'total_inventory' | 'price_min' | 'updated_at', nullable
  - `sort_dir` 'asc' | 'desc'
  - `product_name` string, nullable
  - `product_status` string, nullable: Exact match on product_status, e.g. 'ACTIVATE'.
  - `in_stock_only` boolean: When true, only products with total_inventory > 0.
  - `updated_since` string, date-time, nullable: Return only products Reacher synced on/after this instant. Accepts a plain date (YYYY-MM-DD, treated as midnight UTC) or a full ISO 8601 timestamp — pass the `updated_at` from a previous response verbatim to key an incremental catalog sync.
  - `include_skus` boolean: Embed the per-SKU inventory array on each product.

## Response `200`

Successful Response

- ProductCatalogPaginatedResponse
  - `data` CatalogProductItem[], required
    - `shop_id` integer, required: Reacher shop id that owns this product (useful for multi-shop syncs).
    - `product_id` string, required: TikTok product id.
    - `title` string, nullable
    - `description` string, nullable: Product copy (HTML), from the catalog.
    - `brand_name` string, nullable
    - `category_chain` unknown[]: Category hierarchy as stored by TikTok (leaf-last).
      - unknown
    - `primary_image_url` string, nullable
    - `image_urls` unknown[]: All image URLs for the product (empty when none are set).
      - unknown
    - `currency` string, required: ISO 4217 currency for the *_cents fields.
    - `price_min_cents` integer, nullable: Lowest listed price across SKUs, in cents.
    - `price_max_cents` integer, nullable: Highest listed price across SKUs, in cents.
    - `total_inventory` integer, nullable: Product-level stock reported by TikTok.
    - `sku_count` integer, nullable: Number of SKUs.
    - `out_of_stock_sku_count` integer, nullable: How many SKUs currently have zero stock.
    - `product_status` string, nullable: ACTIVATE / DRAFT / REVIEWING / etc. Null for unofficial shops.
    - `affiliate_status` integer, nullable: TikTok affiliate eligibility (1=ELIGIBLE, 2/6=OUT_OF_STOCK, 3/999=UNAVAILABLE, 4=PLATFORM_DEACTIVATED). Refreshed every sync.
    - `is_cod_allowed` boolean, nullable
    - `tiktok_created_at` string, nullable: When TikTok created the listing (ISO 8601 UTC).
    - `tiktok_updated_at` string, nullable: When TikTok last changed the listing (ISO 8601 UTC).
    - `updated_at` string, nullable: When Reacher last synced this product row (ISO 8601 UTC, microsecond precision). Feed the max value from a batch back as the next request's `updated_since` to drive a best-effort incremental sync. The filter is inclusive (`>=`), so re-fetch the boundary and de-dupe by `product_id`. Deleted products are not returned as tombstones, and a SKU-only change only appears if the sync also advanced this `updated_at` — a full mirror must reconcile deletions out-of-band.
    - `skus` CatalogSkuItem[]: Per-SKU rows with stock. Empty when include_skus=false.
      - `sku_id` string, required: TikTok SKU id.
      - `seller_sku` string, nullable: Merchant's own SKU code.
      - `inventory` integer, required: Current stock for this SKU. This can differ from the product-level total_inventory while a catalog sync is in progress, so do not assume the two always agree.
      - `variants` CatalogSkuVariant[]: Variant dimensions (color/size/etc.) that identify this SKU.
        - `name` string, nullable: Attribute name, e.g. 'Color' or 'Size'.
        - `value_name` string, nullable: Selected value, e.g. 'GOLDEN MEDIUM'.
        - `value_id` string, nullable: TikTok value id for the selected value.
        - `image_url` string, nullable: Variant swatch image for this attribute value.
      - `updated_at` string, nullable: When Reacher last synced this SKU row (ISO 8601 UTC).
  - `pagination` unknown, required
  - `shops_queried` string[], nullable: Shop names included when querying multiple shops (x-shop-id: all or comma-separated).

## Other responses

- `422`: Validation Error

## Changes

> 76 revisions in range; 1 not diffed.

- **2026-09-19** `291230805105`: 1 info
  - api operation id `products_catalog_products_catalog_post` removed and replaced with `products_catalog`
- **2026-09-02** `d4fe3e380424`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/reacherapp/apis/reacher-data-api/changes/products/catalog/post.md)

---

[API](https://skmtc.dev/reacherapp/apis/reacher-data-api.md) - [All operations](https://skmtc.dev/reacherapp/apis/reacher-data-api/llms.txt) - [OpenAPI document](https://skmtc.dev/reacherapp/apis/reacher-data-api/revisions/63ce74b30b5a?raw)
