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.

·8 min read ·Updated 3 Sep 2026

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
}
FieldQuestion it answers
quantityHow many units physically exist, across every warehouse
incomingHow many units are on inbound purchase orders
offered_stockHow 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 buildingUse
A channel listing syncoffered_stock
An ERP availability feedoffered_stock
A physical stock take reconciliationquantity, per warehouse
A replenishment calculationquantity plus incoming
A warehouse picking viewquantities[].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:

  • location is a hierarchical bin, written A1-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.
  • threshold is 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.

A Stockpilot engineer talking through an integration with a developer

Stuck on something

Ask a person, not a search box

The API surface is wide, and some of it only makes sense once someone explains why it works that way. If a payload is not doing what you expect, or you are weighing two approaches, say so and we will look at it with you.