Inventory
Stock by warehouse, the kardex of every movement, adjustments and transfers.
Overview
Inventory keeps the quantity of each product in each warehouse and a kardex (stock_movement) for every change. Stock moves automatically when invoices are issued or cancelled, purchase orders are received, bills are registered and work orders are delivered. Through the API you can read stock levels and movements, and record adjustments and transfers.
Requires the Inventory module. An owner or admin turns it on in Settings > Modules. While it is off, every endpoint on this page returns 403 with type permission_error and code module_disabled.
Warehouses, adjustment reasons and inventory settings (for example allowing negative stock) are configured in the dashboard, in Settings > Inventory. The API lists them but does not create them.
The Stock Level Object
A stock_level has no id: it is keyed by product_id. quantity is the total of every warehouse, value = quantity x avg_cost, and low_stock is true when the product tracks stock, has a reorder_point and its total quantity is at or below it.
Endpoints
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /v1/warehouses | read | List warehouses (include_inactive) |
GET | /v1/stock | read | Stock levels (warehouse_id, product_id, low_stock). Cursor = product_id |
GET | /v1/stock/{product_id} | read | Stock of one product by warehouse |
POST | /v1/stock/{product_id} | write | Set track_stock and reorder_point |
GET | /v1/stock/reasons | read | Adjustment reasons (in, out or both) |
GET | /v1/stock/movements | read | Kardex (product_id, warehouse_id, from, to) |
GET | /v1/stock/adjustments | read | List adjustments (warehouse_id) |
POST | /v1/stock/adjustments | write | Add or remove stock in one warehouse |
GET | /v1/stock/transfers | read | List transfers (warehouse_id = origin or destination) |
POST | /v1/stock/transfers | write | Move stock between two warehouses |
Check Stock
With warehouse_id, quantity and value refer to that warehouse only and warehouses has a single entry; low_stock still uses the total. The list includes every product, also those with track_stock: false.
Create an Adjustment
An adjustment adds (positive quantity) or removes (negative quantity) stock in one warehouse: initial stock, a stock count, damage. unit_cost only applies to positive lines and updates the average cost. If the reason has a direction, it restricts the signs.
- Up to 500 lines; a repeated product is summed
- Every product must track stock (
400"Some products do not track stock.") - Removing more than available returns
409 resource_conflict("Not enough stock for: ...") unless the company allows negative stock lineslists the movements applied;failed_product_ids(only in this response) lists the lines that were rejected- Emits
stock.adjusted, andstock.lowwhen a product crosses its reorder point
Transfer Stock
Quantities must be positive and the warehouses different. Not enough stock in the origin returns 409 resource_conflict. Emits stock.transferred.
Stock Movements (Kardex)
Every change is a stock_movement with a signed quantity, the resulting balance_quantity, the cost, and the source document (reference_type, reference_id and its human document_number).
| movement_type | Source |
|---|---|
in / out | Adjustments |
transfer_in / transfer_out | Transfers |
sale / sale_return | Issued and cancelled invoices, work order deliveries |
purchase / purchase_return | Purchase receipts and bills (and their cancellation) |