Skip to main content
Use GET /api/v1/inventory to answer questions such as “Which products have stock but no Lazada listing in any of my stores?” The endpoint and the inventory assistant use the same stock calculations and listing checks. Requests require catalog:read and the caller’s inventory read permission. The bearer credential determines the organization and permitted inventory. Do not send organizationId.

Find products with stock and no listing

Combine status=in_stock, unlistedMarketplaces=lazada, and groupBy=product:
This returns one page in groups. Each product group includes its identifier, name in label, SKU, and available units in totalQuantity. A parent’s quantity rolls up its active variants. in_stock requires positive available stock, calculated from canonical on-hand stock minus locked units. Use unlistedMarketplaces for the marketplace where listings must be absent. The separate marketplace, country, and storeIds filters narrow the source inventory. For example, marketplace=shopee together with unlistedMarketplaces=lazada finds Shopee-associated inventory without a recorded Lazada listing. To search the whole inventory, omit the source filters.

What counts as listing presence

The absence check covers every organization store for each selected marketplace, independently of source inventory filters. It checks listing identities on the product and its variants, plus exact catalog SKU matches on other product families. SKU matching trims whitespace and ignores case. Disabled and historical listing identities count as recorded presence. Marketplace configuration or a seller SKU alone does not establish that a listing exists. Families without a usable catalog SKU for duplicate matching are excluded from confirmed results and counted in listingPresence.unknownProductCount. listingPresence.source is saved_catalog: the result reflects stored catalog evidence. It does not perform a fresh live check of marketplace shops. The filter supports every marketplace listed in the API reference. Repeat the query parameter to require absence from multiple marketplaces:
A product must have no recorded listing on either selected marketplace to match this example. SDKs accept an array for the same filter.

Retrieve the complete list

Each request returns at most 30 groups. Continue with the returned nextOffset and identical filters until hasMore is false. Reconcile collected rows against totalGroups, rather than stats.totalSKUs, which counts stock-bearing SKUs rather than product groups. The following examples bound requests using the first matching count and reject incomplete or changing results before reporting a complete list.
Python arguments use snake_case, while response keys remain camelCase. AsyncOmni exposes the same method with await. For larger exports, save each successful page and its continuation together. Offset pages are not immutable snapshots; rerun the report if the catalog changes during collection. A failed request or unresolved listing check must remain an incomplete report.

Interpret product records and stock

Separate catalog records can share a SKU. They remain separate report rows; adding their stock together can double-count the same physical inventory. Report distinct SKU counts separately from product-record counts when needed. For general catalog browsing, products.list().items[].stockQuantity is the Products page’s catalog-stock metric. Use inventory totalQuantity when the question is about available units after locks. See the TypeScript SDK, Python SDK, and the generated API reference for the complete endpoint contract. For stock writes and marketplace sync, see catalog inventory updates.