Guide
The inventory model
Why quantity, offered stock and incoming differ, how warehouses feed the offer, and which number to send to a channel or an ERP.
An inventory record carries several numbers that all look like “how many do we have”. They are not interchangeable, and picking the wrong one is the most common bug in a Stockpilot integration.
The three product level numbers
{
"sku": "TSHIRT-BLK-M",
"quantity": 60,
"incoming": 120,
"offered_stock": 38
}
| Field | Question it answers |
|---|---|
quantity | How many units physically exist, across every warehouse |
incoming | How many units are on inbound purchase orders |
offered_stock | How many units Stockpilot advertises to your sales channels |
offered_stock is the one that drives availability. It is derived, not stored: the sum of warehouses flagged to feed the offer, minus buffer stock.
Why they differ
Two mechanisms pull offered_stock away from quantity.
Warehouses that do not feed the offer
Each warehouse carries a sums_onto_offered flag.
"quantities": [
{ "warehouse_id": 1, "name": "Main", "quantity": 44, "sums_onto_offered": true },
{ "warehouse_id": 7, "name": "Amazon FBA", "quantity": 16, "sums_onto_offered": false }
]
Here 16 units sit in Amazon’s fulfilment centres. Amazon sells and ships them directly, so offering them again on Shopify would oversell. They count towards quantity and not towards offered_stock.
Buffer stock
A seller can hold back a buffer so a channel never sees the last few units. Buffer is subtracted after summing the contributing warehouses. In the example above, 44 contributing units minus a buffer of 6 gives an offered_stock of 38.
Which number to use
| You are building | Use |
|---|---|
| A channel listing sync | offered_stock |
| An ERP availability feed | offered_stock |
| A physical stock take reconciliation | quantity, per warehouse |
| A replenishment calculation | quantity plus incoming |
| A warehouse picking view | quantities[].quantity for that warehouse |
Summing quantities[].quantity yourself gives you quantity, not offered_stock. It ignores both the sums_onto_offered flag and buffer stock, and will overstate availability on any seller with more than one warehouse.
The inbound double count
Per warehouse records also carry an inbound figure:
{ "warehouse_id": 1, "name": "Main", "quantity": 44, "inbound": 120, "sums_onto_offered": true }
Do not sum inbound across warehouses. On the default warehouse, per warehouse inbound repeats the product level incoming, because purchase orders land there. Adding the per warehouse values together and comparing to incoming double counts every inbound unit.
Use the product level incoming field.
Locations and thresholds
Two more fields that ride along on an inventory record:
locationis a hierarchical bin, writtenA1-001-01. It is a string. Do not parse it into aisle, rack and shelf unless you know how that specific warehouse is laid out.thresholdis either units (5u) or weeks of cover (33w). The weeks form is demand aware: a fast selling SKU trips its threshold long before a slow one holding the same unit count.
Reading it
GET /inventory
for a page of items, GET /inventory/get
for one by id, sku or barcode, and GET /warehouses/{unique_id}/items
when you need one warehouse’s view specifically.
curl -s "https://api.stockpilot.dev/inventory?page_size=1000" \
-H "X-CLIENT-ID: $SP_CLIENT_ID" \
-H "X-CLIENT-SECRET: $SP_CLIENT_SECRET"
Keeping it fresh
Polling the list works and is the right tool for a nightly reconciliation. For anything closer to real time, subscribe to inventory.stock_changed, which delivers the same fields within seconds of a change. Build it with Sync offered stock to an ERP.
