Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / API reference

API

Inventory API (inventory)

HTTP endpoints of the inventory module under /api/v1/inventory: 51 routes with permissions, schemas, status codes, and error codes.

The inventory module serves warehouses and storage locations, stock levels and availability, goods movements of every posting type, reservations, usage decisions, stock loans, batches, and serial numbers. All 51 endpoints sit under /api/v1/inventory. For business meaning see the Inventory module page.

Group facts

Item Value Source
Base path /api/v1/inventory src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/inventory/module.py:52
Routers 8 router objects in 3 files; listed in the section Endpoint summary src/cluster_erp/modules/inventory/module.py:33
Endpoints 51, counted from the route decorators and add_api_route calls of the routers that register_routes mounts src/cluster_erp/modules/inventory/batches/routes.py, src/cluster_erp/modules/inventory/stock/routes.py, src/cluster_erp/modules/inventory/warehouses/routes.py
Authentication Bearer header or session cookie, resolved by get_current_user; see Authentication and headers src/cluster_erp/modules/auth/guards.py:85-167
Permission guard 51 of 51 routes declare require_permission src/cluster_erp/modules/auth/guards.py:205-240
App entitlement gate require_app("inventory") on every mounted router src/cluster_erp/modules/inventory/module.py:62
Error format JSON body {"error": {...}}; see Errors src/cluster_erp/server/error_handler.py:33-46

Endpoint summary

One row per sub-module folder. The router prefix is added to the base path.

Sub-module Routers Endpoints Router source
warehouses warehouse_router (/warehouses), location_router (/locations) 12 src/cluster_erp/modules/inventory/warehouses/routes.py:33, src/cluster_erp/modules/inventory/warehouses/routes.py:34
stock stock_router (/stock), movement_router (/movements), reservation_router (/reservations), usage_decision_router (/usage-decisions) 29 src/cluster_erp/modules/inventory/stock/routes.py:47, src/cluster_erp/modules/inventory/stock/routes.py:48, src/cluster_erp/modules/inventory/stock/routes.py:49, src/cluster_erp/modules/inventory/stock/routes.py:50
batches batch_router (/batches), serial_router (/serial-numbers) 10 src/cluster_erp/modules/inventory/batches/routes.py:33, src/cluster_erp/modules/inventory/batches/routes.py:34

Warehouses and locations endpoints

Two routers: warehouses (with a dashboard and the locations of a warehouse) and storage locations.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/inventory/warehouses/ list_warehouses warehouse.read none search, is_active, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:66
GET /api/v1/inventory/warehouses/dashboard warehouse_dashboard warehouse.read none none WarehouseDashboardRead 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:99
POST /api/v1/inventory/warehouses/ create_warehouse warehouse.create WarehouseCreate none WarehouseRead 201 src/cluster_erp/modules/inventory/warehouses/routes.py:108
GET /api/v1/inventory/warehouses/{warehouse_id} get_warehouse warehouse.read none none WarehouseRead 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:119
PUT /api/v1/inventory/warehouses/{warehouse_id} update_warehouse warehouse.update WarehouseUpdate none WarehouseRead 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:132
DELETE /api/v1/inventory/warehouses/{warehouse_id} delete_warehouse warehouse.delete none none none 204 src/cluster_erp/modules/inventory/warehouses/routes.py:146
GET /api/v1/inventory/warehouses/{warehouse_id}/locations/ list_warehouse_locations storage_location.read none search, is_active, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:157
GET /api/v1/inventory/locations/ list_locations storage_location.read none warehouse_id, search, is_active, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:198
POST /api/v1/inventory/locations/ create_location storage_location.create StorageLocationCreate none StorageLocationRead 201 src/cluster_erp/modules/inventory/warehouses/routes.py:233
GET /api/v1/inventory/locations/{location_id} get_location storage_location.read none none StorageLocationRead 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:244
PUT /api/v1/inventory/locations/{location_id} update_location storage_location.update StorageLocationUpdate none StorageLocationRead 200 (default) src/cluster_erp/modules/inventory/warehouses/routes.py:257
DELETE /api/v1/inventory/locations/{location_id} delete_location storage_location.delete none none none 204 src/cluster_erp/modules/inventory/warehouses/routes.py:271

Stock, movements, and reservations endpoints

Four routers: stock levels and availability with posting routes (goods receipt and issue, transfer, ownership transfer, loans, adjustment, blocked receipt, category transfer, return to vendor, scrap, subcontracting), movements with reversal, reservations, and usage decisions.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/inventory/stock/levels/ list_stock_levels stock_level.read none product_id, product_model_id, product_version_id, warehouse_id, batch_id, custodian_party_id, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:59
GET /api/v1/inventory/stock/levels/row/{level_id} get_stock_level_row stock_level.read none none StockLevelListRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:93
GET /api/v1/inventory/stock/levels/{product_id} get_stock_level stock_level.read none warehouse_id, product_model_id, product_version_id dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:113
GET /api/v1/inventory/stock/availability/{product_id} check_stock_availability stock_level.read none product_model_id, product_version_id, qty, warehouse_id dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:129
POST /api/v1/inventory/stock/goods-receipt post_goods_receipt goods_movement.create GoodsReceiptCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:156
POST /api/v1/inventory/stock/goods-issue post_goods_issue goods_movement.create GoodsIssueCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:185
POST /api/v1/inventory/stock/transfer post_transfer goods_movement.create TransferCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:201
POST /api/v1/inventory/stock/ownership-transfer post_ownership_transfer goods_movement.create OwnershipTransferCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:217
POST /api/v1/inventory/stock/loans/borrow post_stock_borrow goods_movement.create StockBorrowCreate none ProjectStockLoanRead 201 src/cluster_erp/modules/inventory/stock/routes.py:235
POST /api/v1/inventory/stock/loans/{loan_id}/payback post_stock_payback goods_movement.create StockPaybackCreate none ProjectStockLoanRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:251
GET /api/v1/inventory/stock/loans list_stock_loans stock_level.read none project_id, status, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:267
POST /api/v1/inventory/stock/adjustment post_adjustment goods_movement.create AdjustmentCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:290
POST /api/v1/inventory/stock/gr-blocked-receipt post_gr_blocked_receipt goods_movement.create GrBlockedReceiptCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:306
POST /api/v1/inventory/stock/stock-category-transfer post_stock_category_transfer goods_movement.create StockCategoryTransferCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:322
POST /api/v1/inventory/stock/return-to-vendor post_return_to_vendor goods_movement.create ReturnToVendorCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:341
POST /api/v1/inventory/stock/scrap post_scrap goods_movement.create ScrapPostingCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:357
POST /api/v1/inventory/stock/subcontract-issue post_subcontract_issue goods_movement.create SubcontractStockCreate none dict 201 src/cluster_erp/modules/inventory/stock/routes.py:598
POST /api/v1/inventory/stock/subcontract-return post_subcontract_return goods_movement.create SubcontractStockCreate none dict 201 src/cluster_erp/modules/inventory/stock/routes.py:610
POST /api/v1/inventory/stock/subcontract-consume post_subcontract_consume goods_movement.create SubcontractStockCreate none dict 201 src/cluster_erp/modules/inventory/stock/routes.py:622
POST /api/v1/inventory/movements/{movement_id}/reverse reverse_movement goods_movement.create MovementReversalCreate none GoodsMovementRead 201 src/cluster_erp/modules/inventory/stock/routes.py:376
GET /api/v1/inventory/movements/ list_movements goods_movement.read none product_id, product_model_id, product_version_id, warehouse_id, batch_id, movement_type, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:400
GET /api/v1/inventory/movements/{movement_id} get_movement goods_movement.read none none GoodsMovementRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:434
GET /api/v1/inventory/reservations/ list_reservations stock_reservation.read none product_id, warehouse_id, reference_type, reference_id, status, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:451
POST /api/v1/inventory/reservations/ create_reservation stock_reservation.create StockReservationCreate none StockReservationRead 201 src/cluster_erp/modules/inventory/stock/routes.py:483
POST /api/v1/inventory/reservations/{reservation_id}/consume consume_reservation stock_reservation.create none none StockReservationRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:499
POST /api/v1/inventory/reservations/{reservation_id}/cancel cancel_reservation stock_reservation.create none none StockReservationRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:514
GET /api/v1/inventory/usage-decisions/ list_usage_decisions usage_decision.read none movement_id, product_id, warehouse_id, decision_code, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:532
GET /api/v1/inventory/usage-decisions/{decision_id} get_usage_decision usage_decision.read none none UsageDecisionRead 200 (default) src/cluster_erp/modules/inventory/stock/routes.py:562
POST /api/v1/inventory/usage-decisions/ create_usage_decision usage_decision.create UsageDecisionCreate none UsageDecisionRead 201 src/cluster_erp/modules/inventory/stock/routes.py:579

Batches and serial numbers endpoints

Two routers: batches and serial numbers.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/inventory/batches/ list_batches batch.read none product_id, origin_type, status, search, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:49
POST /api/v1/inventory/batches/ create_batch batch.create BatchCreate none BatchRead 201 src/cluster_erp/modules/inventory/batches/routes.py:87
GET /api/v1/inventory/batches/{batch_id} get_batch batch.read none none BatchRead 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:99
PUT /api/v1/inventory/batches/{batch_id} update_batch batch.update BatchUpdate none BatchRead 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:113
DELETE /api/v1/inventory/batches/{batch_id} delete_batch batch.delete none none none 204 src/cluster_erp/modules/inventory/batches/routes.py:128
GET /api/v1/inventory/serial-numbers/ list_serial_numbers serial_number.read none product_id, batch_id, status, search, limit, offset dict 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:143
POST /api/v1/inventory/serial-numbers/ create_serial_number serial_number.create SerialNumberCreate none SerialNumberRead 201 src/cluster_erp/modules/inventory/batches/routes.py:173
GET /api/v1/inventory/serial-numbers/{serial_id} get_serial_number serial_number.read none none SerialNumberRead 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:185
PUT /api/v1/inventory/serial-numbers/{serial_id} update_serial_number serial_number.update SerialNumberUpdate none SerialNumberRead 200 (default) src/cluster_erp/modules/inventory/batches/routes.py:199
DELETE /api/v1/inventory/serial-numbers/{serial_id} delete_serial_number serial_number.delete none none none 204 src/cluster_erp/modules/inventory/batches/routes.py:214

Error codes

The table lists the error codes that code under src/cluster_erp/modules/inventory/ raises, found by a syntax-tree scan for AppError(...), the factories in src/cluster_erp/core/errors.py (not_found, conflict, protected, permission_denied, privilege_escalation, check_version), and HTTPException(...). A status of 400 is the AppError default (src/cluster_erp/core/errors.py:23). Guard errors (401, 403), the entitlement codes, and validation errors (422) apply to every route and are listed on Errors.

Code HTTP status Raised in First site
INVENTORY_BATCH_EXPIRED 400 stock src/cluster_erp/modules/inventory/stock/services.py:2166
INVENTORY_BATCH_REQUIRED 400 stock src/cluster_erp/modules/inventory/stock/services.py:2143
INVENTORY_DECISION_QTY_EXCEEDS 400 stock src/cluster_erp/modules/inventory/stock/services.py:1527
INVENTORY_INSUFFICIENT_STOCK 400 stock src/cluster_erp/modules/inventory/stock/services.py:853
INVENTORY_INVALID_CATEGORY_TRANSFER 400 stock src/cluster_erp/modules/inventory/stock/services.py:1223
INVENTORY_INVALID_DECISION_CODE 400 stock src/cluster_erp/modules/inventory/stock/services.py:1502
INVENTORY_INVALID_MOVEMENT 409, 422 stock src/cluster_erp/modules/inventory/stock/services.py:553
INVENTORY_INVALID_MOVEMENT_TYPE 400 stock src/cluster_erp/modules/inventory/stock/services.py:332
INVENTORY_INVALID_ORIGIN_TYPE 400 batches src/cluster_erp/modules/inventory/batches/services.py:189
INVENTORY_INVALID_STOCK_CATEGORY 400 stock src/cluster_erp/modules/inventory/stock/services.py:1211
INVENTORY_MOVEMENT_ALREADY_REVERSED 400 stock src/cluster_erp/modules/inventory/stock/services.py:1742
INVENTORY_MOVEMENT_NOT_DECIDABLE 400 stock src/cluster_erp/modules/inventory/stock/services.py:1515
INVENTORY_PO_RECEIPT_REQUIRES_PO_FLOW 409 stock src/cluster_erp/modules/inventory/stock/routes.py:174
INVENTORY_PRODUCT_NOT_STOCKABLE 400 batches, stock src/cluster_erp/modules/inventory/batches/services.py:210
INVENTORY_PROJECT_TRANSFER_DISABLED 403 stock src/cluster_erp/modules/inventory/stock/services.py:563
INVENTORY_RESERVATION_ALREADY_CANCELLED 400 stock src/cluster_erp/modules/inventory/stock/services.py:1998
INVENTORY_RESERVATION_ALREADY_CONSUMED 400 stock src/cluster_erp/modules/inventory/stock/services.py:1992
INVENTORY_RESERVATION_NOT_FOUND 404 stock src/cluster_erp/modules/inventory/stock/services.py:1985
INVENTORY_SERIAL_ALREADY_USED 409 batches, stock src/cluster_erp/modules/inventory/batches/services.py:349
INVENTORY_SERIAL_REQUIRED 400 stock src/cluster_erp/modules/inventory/stock/services.py:2149
RESOURCE_CONFLICT 409 batches, warehouses src/cluster_erp/modules/inventory/batches/services.py:228
RESOURCE_NOT_FOUND 404 batches, stock, warehouses src/cluster_erp/modules/inventory/batches/routes.py:109

Events emitted

The table lists the contract classes that code under src/cluster_erp/modules/inventory/ passes directly to EventBus.emit, found by a syntax-tree scan. Events built in a variable first are not counted. The contracts are described in Contracts reference.

Contract Sites First site
BatchCreated 1 src/cluster_erp/modules/inventory/batches/services.py:134
GoodsIssued 2 src/cluster_erp/modules/inventory/stock/services.py:527
GoodsMovementReversed 1 src/cluster_erp/modules/inventory/stock/services.py:1879
GoodsReceived 1 src/cluster_erp/modules/inventory/stock/services.py:431
GrBlockedReceived 1 src/cluster_erp/modules/inventory/stock/services.py:1181
ReturnedToVendor 1 src/cluster_erp/modules/inventory/stock/services.py:1387
ScrapPosted 1 src/cluster_erp/modules/inventory/stock/services.py:1482
StockAdjusted 1 src/cluster_erp/modules/inventory/stock/services.py:1101
StockCategoryTransferred 2 src/cluster_erp/modules/inventory/stock/services.py:875
StockReservationCancelled 1 src/cluster_erp/modules/inventory/stock/services.py:2073
StockReservationConsumed 1 src/cluster_erp/modules/inventory/stock/services.py:2020
StockReserved 1 src/cluster_erp/modules/inventory/stock/services.py:1957
StockTransferred 1 src/cluster_erp/modules/inventory/stock/services.py:1039
UsageDecisionRecorded 1 src/cluster_erp/modules/inventory/stock/services.py:1653

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13