{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Inventory"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"inventory","__idx":0},"children":["Inventory"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Applies to the Fulfilment API only."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Inventory is read-only in normal operation. It is the warehouse's count, not yours. It appears when an inbound is received and it moves when orders are picked."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"reading-stock","__idx":1},"children":["Reading stock"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /api/fulfilment/inventory"]}," lists everything under your account. Filter with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sku"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["product_name"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vendor"]},", page with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["limit"]}," (1 to 100, default 20) and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["page"]}," (starts at 1), sort with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sort"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sort_desc"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /api/fulfilment/inventory/{sku}"]}," gives one SKU. It takes the SKU, not a product id."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-buckets","__idx":2},"children":["The buckets"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A quantity is never just a quantity. Every SKU splits across buckets, and only one of them is sellable."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Bucket"},"children":["Bucket"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Meaning"},"children":["Meaning"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["available"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["On the shelf, sellable, not promised to anything."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reserved"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Committed to an order that is being picked."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["damaged"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Written off."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["qc_hold"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Held for quality inspection."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["total"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The sum of all buckets."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Sell against ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["available"]},", not ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["total"]},"."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["total"]}," includes stock that is already promised, already broken, or already quarantined. Reading ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["total"]}," as availability is the most common way to oversell."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reserved"]}," moves on its own as orders progress. You do not manage it."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"batches-and-expiry","__idx":3},"children":["Batches and expiry"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a SKU with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch_management"]}," switched on, the quantity above is a roll-up."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /api/fulfilment/inventory/{sku}/batches"]}," breaks it down by batch: batch number, expiry date, manufacturing date and the batch's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["available"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unusable"]}," quantities. Filter with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["batch_number"]},", or with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["expiring_before"]}," to find stock about to age out."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /api/fulfilment/batches/{batchId}"]}," returns a single batch."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An inventory item also carries ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["expiry_groups"]},", grouping quantity by expiry date without the full batch detail."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Which batch gets picked is decided by the warehouse, using the product's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["outbound_expiry_threshold_days"]},". You do not choose it per order."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"adjusting-stock","__idx":4},"children":["Adjusting stock"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /api/fulfilment/inventory/adjustments"]}," writes a manual correction against one bucket: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sku"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["bucket"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quantity_change"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reason"]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["damage"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["correction"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["write_off"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["qc_fail"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["other"]},") and optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["notes"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The adjustment is a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["delta"]},", positive or negative, not a new total. It is recorded as an inventory movement, so it is auditable. The SKU must already have an inventory record, and a change that would take a bucket below zero is rejected."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use it for writing off damage found after receipt, correcting a discrepancy after a physical count, or moving stock into QC hold. Do not use it to load opening stock. That is what an ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/fulfilment/inbound"},"children":["inbound"]}," is for."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"stock-change-events","__idx":5},"children":["Stock change events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Stock changes attributed to a received inbound, a picked or cancelled order, or an adjustment are published as an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["inventory.moved"]}," webhook. One event groups the movements that share a cause. For each SKU it carries the change, the bucket and the stock levels after the change (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["available"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["damaged"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reserved"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["qc_hold"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["total"]},"), with a reference to the inbound, order or adjustment behind it."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use it as a prompt to refresh, not as a ledger to sum: the inventory endpoints above are the count. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/webhooks"},"children":["Webhooks"]},"."]}]},"headings":[{"value":"Inventory","id":"inventory","depth":1},{"value":"Reading stock","id":"reading-stock","depth":2},{"value":"The buckets","id":"the-buckets","depth":2},{"value":"Batches and expiry","id":"batches-and-expiry","depth":2},{"value":"Adjusting stock","id":"adjusting-stock","depth":2},{"value":"Stock change events","id":"stock-change-events","depth":2}],"frontmatter":{"seo":{"title":"Inventory"}},"lastModified":"2026-10-16T10:31:15.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/fulfilment/inventory","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}