> For the complete documentation index, see [llms.txt](https://docs.flowretail.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flowretail.com/docs/developers/api-documentation/reports/shelf-warmers-search.md).

# Shelf warmers search

Get products whose stock stands still — so-called shelf warmers or dead stock. The condition is judged per warehouse: a warehouse qualifies when it holds stock of the product and that stock has had no movement since `noActivitySince`. A product is listed when at least one of the matching warehouses qualifies, so stock standing still in one store is reported there even if another store sold the same product yesterday. Quantity in stock, stock value, last received and last stock change count only the warehouses that qualify. Without `noActivitySince` every warehouse holding stock qualifies, so the report lists the whole stock.

Each JSON row is one product aggregated across the qualifying warehouses, with a per-warehouse breakdown, last sold/received/stock-change dates and supplier info.

Optionally filtered on organization, store, warehouse, supplier, product group (incl. descendants), category (incl. descendants), brand and a free-text search on SKU/name.

Sortable by: stockValue (default, DESC), qtyStock, lastSoldAt, lastReceivedAt, lastStockChangeAt, sku, name.

Set accept header to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet to get the response as an excel file. The export is not paginated and has one row per warehouse and stock-in day rather than one summed row per product, so you can see how long each batch of stock has been standing: stock on hand is traced back to the days it came in, assuming the oldest units are sold first, and a product's rows read oldest stock first. Stock that cannot be traced to a logged movement gets a row without a date, placed last. Columns: SKU, product name, brand, product group, properties, GTINs, suppliers, store, warehouse, stock in, days since stock in, last sold, last stock change, quantity in stock, unit cost, stock value. A report that would exceed 100 000 rows is rejected with a 400 — narrow it with a filter.

"Stock in" is the day the units last entered the warehouse by any movement that added stock — a receive, but also a customer return, a stock count correction, an import, an RMA, a manual adjustment or a transfer in from another store. It is therefore not a goods-receipt date and not the age of the goods: returning or moving a single unit starts the count over for that unit, while the rest of the batch keeps its older day. Use `lastReceivedAt` for the strict goods-receipt date.

```json
{"openapi":"3.0.2","info":{"title":"Flow Retail API version 2","version":"2.0.0"},"tags":[{"name":"Reports","description":"Reports"}],"servers":[{"description":"Flow Retail Production","url":"https://api.flowretail.com/v2"},{"description":"Flow Retail Stage","url":"https://api.stage.flowretail.com/v2"}],"security":[{"accessToken":[]},{"authToken":[]},{"integrationToken":[]}],"components":{"securitySchemes":{"accessToken":{"description":"Access token recevied after user login with a deviceToken","scheme":"bearer","type":"http"},"authToken":{"description":"Token received from the auth service","scheme":"bearer","type":"http"},"integrationToken":{"scheme":"bearer","type":"http"}},"parameters":{"pageNumberQuery":{"description":"Reference to a specific page in a result set.","in":"query","name":"pageNumber","required":false,"schema":{"type":"integer"}},"pageSizeQuery":{"description":"The number of items per page in a result set.","in":"query","name":"pageSize","required":false,"schema":{"type":"integer"}},"sortByQuery":{"description":"Defines which field the resource list is sorted by.","in":"query","name":"sortBy","required":false,"schema":{"type":"string"}},"sortDirectionQuery":{"description":"Reference to a sort direction","explode":false,"in":"query","name":"sortDirection","schema":{"$ref":"#/components/schemas/SortDirectionENUM"},"style":"form"}},"schemas":{"SortDirectionENUM":{"description":"|ENUM      | Description |\n| ---------------- | ------------ |\n| ASC | Sort in ascending order|\n| DESC | Sort in descending order|\n","enum":["ASC","DESC"],"title":"SortDirectionENUM","type":"string"},"ShelfWarmerResponseSchema":{"type":"object","required":["product","qtyStock","stockValue","lastSoldAt","lastReceivedAt","lastStockChangeAt","warehouses","suppliers"],"properties":{"product":{"$ref":"#/components/schemas/ShelfWarmerProductSchema"},"qtyStock":{"type":"integer","description":"Total stock across the matching warehouses, in hundredths (100 = 1.00)."},"stockValue":{"type":"integer","description":"Total stock value across the matching warehouses, in the tenant currency's minor unit."},"lastSoldAt":{"type":"string","format":"date-time","nullable":true,"description":"Most recent completed sale, scoped to the selected stores. Null if never sold."},"lastReceivedAt":{"type":"string","format":"date-time","nullable":true,"description":"Most recent goods receipt in the matching warehouses. Null if never received."},"lastStockChangeAt":{"type":"string","format":"date-time","nullable":true,"description":"Most recent warehouse stock movement in the matching warehouses, including stock imports. Null if no logged stock transaction."},"warehouses":{"type":"array","description":"Per-warehouse stock breakdown. Empty if none match.","items":{"$ref":"#/components/schemas/ShelfWarmerWarehouseSchema"}},"suppliers":{"type":"array","description":"Suppliers for the product. Empty if none.","items":{"$ref":"#/components/schemas/ShelfWarmerSupplierSchema"}}}},"ShelfWarmerProductSchema":{"type":"object","required":["productUid","sku","name","brandUid","brandName","gtins","productGroupUid","productGroupName","productGroupPath","categories","properties"],"properties":{"productUid":{"$ref":"#/components/schemas/UID"},"sku":{"type":"string"},"name":{"type":"string"},"brandUid":{"$ref":"#/components/schemas/UID"},"brandName":{"type":"string"},"gtins":{"type":"array","description":"Empty if the product has no GTINs.","items":{"type":"string"}},"productGroupUid":{"$ref":"#/components/schemas/UID"},"productGroupName":{"type":"string"},"productGroupPath":{"type":"array","description":"The product group's full path, root first, ending with the group the product sits in. Always present. Every product belongs to a product group, so this normally has at least one entry; it is empty only when the group could not be resolved, for instance because it was deleted while the report was running. Do not index the last element without checking the length.\n","items":{"$ref":"#/components/schemas/ShelfWarmerProductGroupRefSchema"}},"categories":{"type":"array","description":"Empty if the product has no categories.","items":{"$ref":"#/components/schemas/ShelfWarmerCategoryRefSchema"}},"properties":{"type":"array","description":"Empty if the product has no properties.","items":{"$ref":"#/components/schemas/ShelfWarmerPropertySchema"}}}},"UID":{"title":"UID","type":"string","pattern":"^[A-Za-z0-9-_]+"},"ShelfWarmerProductGroupRefSchema":{"type":"object","required":["productGroupUid","name"],"properties":{"productGroupUid":{"$ref":"#/components/schemas/UID"},"name":{"type":"string"}}},"ShelfWarmerCategoryRefSchema":{"type":"object","required":["categoryUid","name"],"properties":{"categoryUid":{"$ref":"#/components/schemas/UID"},"name":{"type":"string"}}},"ShelfWarmerPropertySchema":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string","description":"Empty string if the property has no value."}}},"ShelfWarmerWarehouseSchema":{"type":"object","required":["warehouseUid","name","store","qtyStock","averageCost","stockLayers","lastSoldAt","lastStockChangeAt"],"properties":{"warehouseUid":{"$ref":"#/components/schemas/UID"},"name":{"type":"string"},"store":{"$ref":"#/components/schemas/ShelfWarmerStoreRefSchema"},"qtyStock":{"type":"integer","description":"Stock in this warehouse, in hundredths."},"averageCost":{"type":"integer","description":"Average unit cost in the tenant currency's minor unit."},"stockLayers":{"type":"array","description":"This warehouse's stock split over the days it last came in on, oldest first, with an undated layer last. Always present, and empty when the request did not ask for it with includeStockLayers — an empty breakdown therefore does not mean the warehouse holds no stock. Read qtyStock for that.\n","items":{"$ref":"#/components/schemas/ShelfWarmerStockLayerSchema"}},"lastSoldAt":{"type":"string","format":"date-time","nullable":true,"description":"Most recent completed sale of the product in this warehouse's store. Null if never sold there, if the warehouse has no store, or if the request did not ask for it with includeStockLayers. A store is the finest scope a sale can be attributed to, since order lines do not reliably carry a warehouse.\n"},"lastStockChangeAt":{"type":"string","format":"date-time","nullable":true,"description":"Most recent logged stock movement on this warehouse's stock, including imports. Null if there is no logged transaction, or if the request did not ask for it with includeStockLayers.\n"}}},"ShelfWarmerStoreRefSchema":{"type":"object","nullable":true,"description":"The store this warehouse belongs to. Null if the warehouse is not tied to a store.","required":["storeUid","name","organizationUid","organizationName"],"properties":{"storeUid":{"$ref":"#/components/schemas/UID"},"name":{"type":"string"},"organizationUid":{"$ref":"#/components/schemas/UID"},"organizationName":{"type":"string"}}},"ShelfWarmerStockLayerSchema":{"type":"object","description":"One FIFO layer of the stock still on hand in a warehouse: the day it last came in, and how much of it is left.\n","required":["stockInOn","qtyStock"],"properties":{"stockInOn":{"type":"string","format":"date","nullable":true,"description":"The day the units last came into the warehouse, by any positive stock movement — a goods receipt, but also a customer return, a stock count correction, an import, an RMA or a transfer in from another store. Not a goods-receipt date, and so not the age of the goods either: returning or moving a single unit resets this day for that unit while the rest of the batch keeps its older one. Null when the stock cannot be traced to a logged movement at all, for instance older imported stock.\n"},"qtyStock":{"type":"integer","description":"The part of the warehouse stock that came in on that day, in hundredths."}}},"ShelfWarmerSupplierSchema":{"type":"object","required":["supplierUid","name","supplierSku","purchasePrice"],"properties":{"supplierUid":{"$ref":"#/components/schemas/UID"},"name":{"type":"string"},"supplierSku":{"type":"string","description":"Empty string if not set."},"purchasePrice":{"type":"integer","description":"Supplier purchase price in the tenant currency's minor unit."}}},"Paging":{"description":"totalCount The total number of items in the result set.\n\npageSize The number of items per page.\n\npageNumber The current page in the result set.","properties":{"pageNumber":{"type":"integer"},"pageSize":{"type":"integer"},"totalCount":{"type":"integer"}},"required":["totalCount","pageSize","pageNumber"],"title":"Paging","type":"object"}},"responses":{"ShelfWarmersListResponse":{"description":"Shelf warmer search results","content":{"application/json":{"schema":{"type":"object","required":["items","paging"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ShelfWarmerResponseSchema"}},"paging":{"$ref":"#/components/schemas/Paging"}}}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}}}}},"requestBodies":{"ShelfWarmerSearchRequest":{"content":{"application/json":{"schema":{"type":"object","properties":{"noActivitySince":{"type":"string","format":"date-time","description":"Products with no stock movement after this time are considered shelf warmers. Leave it out to list all stock."},"organizationUids":{"type":"array","items":{"$ref":"#/components/schemas/UID"}},"storeUids":{"type":"array","items":{"$ref":"#/components/schemas/UID"}},"warehouseUids":{"type":"array","items":{"$ref":"#/components/schemas/UID"}},"supplierUids":{"type":"array","items":{"$ref":"#/components/schemas/UID"}},"productGroupUids":{"type":"array","description":"Includes descendant product groups.","items":{"$ref":"#/components/schemas/UID"}},"categoryUids":{"type":"array","description":"Includes descendant categories.","items":{"$ref":"#/components/schemas/UID"}},"brandUids":{"type":"array","items":{"$ref":"#/components/schemas/UID"}},"query":{"type":"string","description":"Free-text search across product SKU and name."},"includeStockLayers":{"type":"boolean","description":"When true, every warehouse in the response carries its stock split over the days it last came in on (oldest first), plus that warehouse's own last sale and last stock movement. Costs two extra queries, so leave it out unless the caller shows the breakdown. Defaults to false.\n"}}}}}}}},"paths":{"/tenants/{tenantUid}/reports/shelf-warmers":{"post":{"summary":"Shelf warmers search","tags":["Reports"],"operationId":"shelf-warmers-search","description":"Get products whose stock stands still — so-called shelf warmers or dead\nstock. The condition is judged per warehouse: a warehouse qualifies when\nit holds stock of the product and that stock has had no movement since\n`noActivitySince`. A product is listed when at least one of the matching\nwarehouses qualifies, so stock standing still in one store is reported\nthere even if another store sold the same product yesterday. Quantity in\nstock, stock value, last received and last stock change count only the\nwarehouses that qualify. Without `noActivitySince` every warehouse holding\nstock qualifies, so the report lists the whole stock.\n\nEach JSON row is one product aggregated across the qualifying warehouses,\nwith a per-warehouse breakdown, last sold/received/stock-change dates and\nsupplier info.\n\nOptionally filtered on organization, store, warehouse, supplier, product\ngroup (incl. descendants), category (incl. descendants), brand and a\nfree-text search on SKU/name.\n\nSortable by: stockValue (default, DESC), qtyStock, lastSoldAt,\nlastReceivedAt, lastStockChangeAt, sku, name.\n\nSet accept header to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\nto get the response as an excel file. The export is not paginated and has\none row per warehouse and stock-in day rather than one summed row per\nproduct, so you can see how long each batch of stock has been standing:\nstock on hand is traced back to the days it came in, assuming the oldest\nunits are sold first, and a product's rows read oldest stock first. Stock\nthat cannot be traced to a logged movement gets a row without a date,\nplaced last. Columns: SKU, product name, brand, product group,\nproperties, GTINs, suppliers, store, warehouse, stock in, days since\nstock in, last sold, last stock change, quantity in stock, unit cost,\nstock value. A report that would exceed 100 000 rows is rejected with a\n400 — narrow it with a filter.\n\n\"Stock in\" is the day the units last entered the warehouse by any\nmovement that added stock — a receive, but also a customer return, a\nstock count correction, an import, an RMA, a manual adjustment or a\ntransfer in from another store. It is therefore not a goods-receipt date\nand not the age of the goods: returning or moving a single unit starts\nthe count over for that unit, while the rest of the batch keeps its older\nday. Use `lastReceivedAt` for the strict goods-receipt date.","parameters":[{"$ref":"#/components/parameters/pageNumberQuery"},{"$ref":"#/components/parameters/pageSizeQuery"},{"$ref":"#/components/parameters/sortByQuery"},{"$ref":"#/components/parameters/sortDirectionQuery"}],"responses":{"200":{"$ref":"#/components/responses/ShelfWarmersListResponse"}},"requestBody":{"$ref":"#/components/requestBodies/ShelfWarmerSearchRequest"}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.flowretail.com/docs/developers/api-documentation/reports/shelf-warmers-search.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
