Products
GET /v1/catalog/products
(paginated list) and
GET /v1/catalog/products/{id}
(single product). Required scope: catalog.products.read.
What a product row tells you
Section titled “What a product row tells you”Identity (id, sku, barcode), display info (name, brand, size), classification
(categoryId, unitType, taxCategory, vatRate), selling price (sellingPriceGross,
sellingPriceNet - both, since which one you need depends on how you’re displaying it),
isActive, variablePrice (sold by weight/scale rather than a fixed unit price), and four
independent restriction flags: ageRestricted, alcoholRestricted, tobaccoRestricted,
vapeRestricted - a product can be more than one, or none.
Filters
Section titled “Filters”storeId, categoryId, sku, barcode, q (free-text search across name/SKU/barcode/brand),
updatedSince, activeOnly (default true), plus page/pageSize. See
API Overview for pagination/dates/tenant-scope conventions shared by every route.
Getting one product
Section titled “Getting one product”GET /v1/catalog/products/{id} returns 404 not_found for an ID that doesn’t exist, or exists
outside your tenant/allowed stores - the two cases are indistinguishable by design.
What’s excluded
Section titled “What’s excluded”Cost price, pack/unit cost, margin percent, stock cost layers, supplier mappings, stock movement
history, and any internal-only pricing metadata. catalog.products.read grants catalog/pricing
visibility for display purposes - not access to what EPOS pays for the product.
Related
Section titled “Related”- Inventory Stock - stock levels for these same products, under a separate scope.
- Catalog Sync - a practical sync pattern using
updatedSince.