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

API

Sales orders API (sales_orders)

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

The sales_orders module serves sales orders with PO checks, revisions, milestones, and status steps, order lines with BOM creation, units, shipments with lines, units, packages, and events, trade documents, and chain settings. All 68 endpoints sit under /api/v1/sales_orders. For business meaning see the Sales orders module page.

Group facts

Item Value Source
Base path /api/v1/sales_orders src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/sales_orders/module.py:61
Routers 6 router objects in 6 files; listed in the section Endpoint summary src/cluster_erp/modules/sales_orders/module.py:38
Endpoints 68, counted from the route decorators and add_api_route calls of the routers that register_routes mounts src/cluster_erp/modules/sales_orders/order_lines/routes.py, src/cluster_erp/modules/sales_orders/orders/routes.py, src/cluster_erp/modules/sales_orders/settings/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 68 of 68 routes declare require_permission src/cluster_erp/modules/auth/guards.py:205-240
App entitlement gate require_app("sales_orders") on every mounted router src/cluster_erp/modules/sales_orders/module.py:71
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
shipments router 32 src/cluster_erp/modules/sales_orders/shipments/routes.py:40
units router 5 src/cluster_erp/modules/sales_orders/units/routes.py:21
trade_documents router 4 src/cluster_erp/modules/sales_orders/trade_documents/routes.py:24
settings router 3 src/cluster_erp/modules/sales_orders/settings/routes.py:16
orders router 17 src/cluster_erp/modules/sales_orders/orders/routes.py:33
order_lines router 7 src/cluster_erp/modules/sales_orders/order_lines/routes.py:24

Shipments endpoints

Shipments of an order and of all orders, status steps (ready, ship, in transit, deliver, hold, resume, cancel), shipment lines, shipment units, packages, and shipment events.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/sales-orders/shipments/ list_shipments shipment.read none sales_order_id, project_id, status, search, limit, offset dict 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:85
GET /api/v1/sales_orders/sales-orders/{order_id}/shipments list_order_shipments shipment.read none none list[ShipmentRead] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:121
POST /api/v1/sales_orders/sales-orders/{order_id}/shipments create_shipment shipment.create ShipmentCreate none ShipmentRead 201 src/cluster_erp/modules/sales_orders/shipments/routes.py:135
GET /api/v1/sales_orders/sales-orders/shipments/{shipment_id} get_shipment shipment.read none none ShipmentDetailRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:151
PATCH /api/v1/sales_orders/sales-orders/shipments/{shipment_id} update_shipment shipment.update ShipmentUpdate none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:164
GET /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/order-lines shipment_order_lines shipment.read none none list[dict[str, Any]] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:179
GET /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/available-units shipment_available_units shipment.read none none list[dict[str, Any]] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:192
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/ready ready_shipment shipment.update none none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:208
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/ship ship_shipment shipment.dispatch none none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:219
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/in-transit in_transit_shipment shipment.update InTransitBody none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:230
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/deliver deliver_shipment shipment.deliver DeliverBody \| None none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:242
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/hold hold_shipment shipment.update ReasonBody none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:254
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/resume resume_shipment shipment.update none none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:266
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/cancel cancel_shipment shipment.cancel ReasonBody none ShipmentRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:277
GET /api/v1/sales_orders/sales-orders/shipment-lines/ list_shipment_lines shipment_line.read none shipment_id list[ShipmentLineRead] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:292
GET /api/v1/sales_orders/sales-orders/shipment-lines/{line_id} get_shipment_line shipment_line.read none none ShipmentLineRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:303
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/lines add_shipment_line shipment_line.create ShipmentLineInput none ShipmentLineRead 201 src/cluster_erp/modules/sales_orders/shipments/routes.py:316
PUT /api/v1/sales_orders/sales-orders/shipment-lines/{line_id} update_shipment_line shipment_line.update ShipmentLineUpdate none ShipmentLineRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:332
DELETE /api/v1/sales_orders/sales-orders/shipment-lines/{line_id} remove_shipment_line shipment_line.delete none none none 204 src/cluster_erp/modules/sales_orders/shipments/routes.py:344
GET /api/v1/sales_orders/sales-orders/shipment-units/ list_shipment_units shipment_unit.read none shipment_id list[ShipmentUnitRead] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:357
GET /api/v1/sales_orders/sales-orders/shipment-units/{row_id} get_shipment_unit shipment_unit.read none none ShipmentUnitRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:368
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/units add_shipment_unit shipment_unit.create ShipmentUnitCreate none ShipmentUnitRead 201 src/cluster_erp/modules/sales_orders/shipments/routes.py:381
PUT /api/v1/sales_orders/sales-orders/shipment-units/{row_id} update_shipment_unit shipment_unit.update ShipmentUnitUpdate none ShipmentUnitRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:397
DELETE /api/v1/sales_orders/sales-orders/shipment-units/{row_id} remove_shipment_unit shipment_unit.delete none none none 204 src/cluster_erp/modules/sales_orders/shipments/routes.py:409
GET /api/v1/sales_orders/sales-orders/packages/ list_packages shipment_package.read none shipment_id list[PackageRead] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:422
GET /api/v1/sales_orders/sales-orders/packages/{package_id} get_package shipment_package.read none none PackageRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:433
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/packages add_package shipment_package.create PackageCreate none PackageRead 201 src/cluster_erp/modules/sales_orders/shipments/routes.py:443
PUT /api/v1/sales_orders/sales-orders/packages/{package_id} update_package shipment_package.update PackageUpdate none PackageRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:459
DELETE /api/v1/sales_orders/sales-orders/packages/{package_id} remove_package shipment_package.delete none none none 204 src/cluster_erp/modules/sales_orders/shipments/routes.py:471
GET /api/v1/sales_orders/sales-orders/shipment-events/ list_shipment_events shipment_event.read none shipment_id list[ShipmentEventRead] 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:484
GET /api/v1/sales_orders/sales-orders/shipment-events/{event_id} get_shipment_event shipment_event.read none none ShipmentEventRead 200 (default) src/cluster_erp/modules/sales_orders/shipments/routes.py:495
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/events add_shipment_event shipment_event.create ShipmentEventCreate none ShipmentEventRead 201 src/cluster_erp/modules/sales_orders/shipments/routes.py:508

Units endpoints

Units of an order line and unit generation.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/sales-orders/units/ list_units sales_order_unit.read none sales_order_id, sales_order_line_id, project_id, status, unshipped, search, limit, offset dict 200 (default) src/cluster_erp/modules/sales_orders/units/routes.py:24
POST /api/v1/sales_orders/sales-orders/lines/{line_id}/units create_unit sales_order_unit.create UnitCreate none UnitRead 201 src/cluster_erp/modules/sales_orders/units/routes.py:56
POST /api/v1/sales_orders/sales-orders/lines/{line_id}/generate-units generate_units sales_order_unit.create GenerateUnitsBody none list[UnitRead] 201 src/cluster_erp/modules/sales_orders/units/routes.py:70
GET /api/v1/sales_orders/sales-orders/units/{unit_id} get_unit sales_order_unit.read none none UnitRead 200 (default) src/cluster_erp/modules/sales_orders/units/routes.py:86
PUT /api/v1/sales_orders/sales-orders/units/{unit_id} update_unit sales_order_unit.update UnitUpdate none UnitRead 200 (default) src/cluster_erp/modules/sales_orders/units/routes.py:99

Trade documents endpoints

Trade documents, download, and generation for a shipment.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/sales-orders/trade-documents/ list_trade_documents trade_document.read none shipment_id, sales_order_id, doc_type, current_only, search, limit, offset dict 200 (default) src/cluster_erp/modules/sales_orders/trade_documents/routes.py:37
GET /api/v1/sales_orders/sales-orders/trade-documents/{document_id} get_trade_document trade_document.read none none TradeDocumentDetailRead 200 (default) src/cluster_erp/modules/sales_orders/trade_documents/routes.py:68
GET /api/v1/sales_orders/sales-orders/trade-documents/{document_id}/download download_trade_document trade_document.read none none Response 200 (default) src/cluster_erp/modules/sales_orders/trade_documents/routes.py:84
POST /api/v1/sales_orders/sales-orders/shipments/{shipment_id}/generate-documents generate_documents trade_document.create GenerateDocumentsBody \| None none list[TradeDocumentRead] 201 src/cluster_erp/modules/sales_orders/trade_documents/routes.py:102

Chain settings endpoints

The order-to-shipment chain settings row.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/settings/chain/ list_chain_settings sales_order_settings.read none none list[SalesOrderSettingsRead] 200 (default) src/cluster_erp/modules/sales_orders/settings/routes.py:19
GET /api/v1/sales_orders/settings/chain/{settings_id} get_chain_settings sales_order_settings.read none none SalesOrderSettingsRead 200 (default) src/cluster_erp/modules/sales_orders/settings/routes.py:30
PATCH /api/v1/sales_orders/settings/chain/{settings_id} update_chain_settings sales_order_settings.update SalesOrderSettingsUpdate none SalesOrderSettingsRead 200 (default) src/cluster_erp/modules/sales_orders/settings/routes.py:44

Sales orders endpoints

Orders created from a customer PO, PO checks, revision request and revised PO receipt, accept, status advance, cancel, hold, resume, milestones, and PO revisions.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/sales-orders/ list_orders sales_order.read none search, status, customer_id, limit, offset dict 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:52
POST /api/v1/sales_orders/sales-orders/from-po create_from_po sales_order.create SalesOrderCreate none SalesOrderRead 201 src/cluster_erp/modules/sales_orders/orders/routes.py:86
GET /api/v1/sales_orders/sales-orders/{order_id} get_order sales_order.read none none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:98
POST /api/v1/sales_orders/sales-orders/{order_id}/run-po-check run_po_check sales_order.create none none PoCheckRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:115
GET /api/v1/sales_orders/sales-orders/{order_id}/po-checks list_po_checks sales_order.read none none list[PoCheckRead] 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:130
POST /api/v1/sales_orders/sales-orders/{order_id}/request-revision request_revision sales_order.create RequestRevisionBody none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:148
POST /api/v1/sales_orders/sales-orders/{order_id}/receive-revised-po receive_revised_po sales_order.create SalesOrderCreate none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:164
POST /api/v1/sales_orders/sales-orders/{order_id}/accept accept_order sales_order.accept none none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:183
POST /api/v1/sales_orders/sales-orders/{order_id}/advance/{target_status} advance_status sales_order.create none none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:201
POST /api/v1/sales_orders/sales-orders/{order_id}/cancel cancel_order sales_order.cancel CancelOrderBody none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:220
POST /api/v1/sales_orders/sales-orders/{order_id}/hold hold_order sales_order.create HoldOrderBody none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:239
POST /api/v1/sales_orders/sales-orders/{order_id}/resume resume_order sales_order.create none none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:255
PATCH /api/v1/sales_orders/sales-orders/{order_id} update_order sales_order.create SalesOrderUpdate none SalesOrderRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:273
GET /api/v1/sales_orders/sales-orders/{order_id}/milestones list_milestones sales_order.read none none list[MilestoneRead] 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:292
PATCH /api/v1/sales_orders/sales-orders/{order_id}/milestones/{milestone_type} update_milestone sales_order.create MilestoneUpdate none MilestoneRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:307
GET /api/v1/sales_orders/sales-orders/{order_id}/po-revisions list_po_revisions po_revision.read none none list[PoRevisionRead] 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:327
GET /api/v1/sales_orders/sales-orders/po-revisions/{revision_id} get_po_revision po_revision.read none none PoRevisionDetailRead 200 (default) src/cluster_erp/modules/sales_orders/orders/routes.py:338

Order lines endpoints

Lines of an order and BOM creation for a line.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/sales_orders/sales-orders/{order_id}/lines list_order_lines sales_order.read none none list[SalesOrderLineRead] 200 (default) src/cluster_erp/modules/sales_orders/order_lines/routes.py:27
POST /api/v1/sales_orders/sales-orders/{order_id}/lines create_order_line sales_order.create SalesOrderLineCreate none SalesOrderLineRead 201 src/cluster_erp/modules/sales_orders/order_lines/routes.py:42
GET /api/v1/sales_orders/sales-orders/lines/{line_id} get_order_line sales_order.read none none SalesOrderLineRead 200 (default) src/cluster_erp/modules/sales_orders/order_lines/routes.py:59
PUT /api/v1/sales_orders/sales-orders/lines/{line_id} update_order_line sales_order.create SalesOrderLineUpdate none SalesOrderLineRead 200 (default) src/cluster_erp/modules/sales_orders/order_lines/routes.py:75
DELETE /api/v1/sales_orders/sales-orders/lines/{line_id} delete_order_line sales_order.delete none none none 204 src/cluster_erp/modules/sales_orders/order_lines/routes.py:91
POST /api/v1/sales_orders/sales-orders/lines/{line_id}/create-bom create_bom_for_order_line CreateBomForProduct.REQUIRED_PERMISSION none none dict 200 (default) src/cluster_erp/modules/sales_orders/order_lines/routes.py:106
POST /api/v1/sales_orders/sales-orders/lines/bulk-delete bulk_delete_order_lines sales_order.bulk_delete BulkDeleteRequest none BulkDeleteResponse 200 (default) src/cluster_erp/modules/sales_orders/order_lines/routes.py:165

Error codes

The table lists the error codes that code under src/cluster_erp/modules/sales_orders/ 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
CONCURRENCY_VERSION_CONFLICT 409 order_lines, orders, settings, shipments, units src/cluster_erp/modules/sales_orders/order_lines/services.py:103
ORDER_INVALID_STATUS 400, 409, 422 orders, shipments src/cluster_erp/modules/sales_orders/orders/services.py:194
ORDER_PO_CHECK_REQUIRED 400 orders src/cluster_erp/modules/sales_orders/orders/services.py:603
RESOURCE_CONFLICT 409 units src/cluster_erp/modules/sales_orders/units/services.py:187
RESOURCE_NOT_FOUND 404 order_lines, orders, settings, shipments, trade_documents, units src/cluster_erp/modules/sales_orders/order_lines/routes.py:71
SALES_DELIVERY_NON_WORKING 422 orders src/cluster_erp/modules/sales_orders/orders/services.py:108
SALES_ORDER_LINE_NO_PRODUCT 422 order_lines src/cluster_erp/modules/sales_orders/order_lines/routes.py:143
SHIPMENT_CHECK_FAILED 409, 422 shipments src/cluster_erp/modules/sales_orders/shipments/services.py:810
SHIPMENT_INVALID_STATUS 400 shipments src/cluster_erp/modules/sales_orders/shipments/services.py:1062
TRADE_DOCUMENT_BLOCKED 404, 422 trade_documents src/cluster_erp/modules/sales_orders/trade_documents/services.py:66
UNIT_FROZEN 409 units src/cluster_erp/modules/sales_orders/units/services.py:283
UNIT_LIMIT_EXCEEDED 409, 422 units src/cluster_erp/modules/sales_orders/units/services.py:201
VALIDATION_ERROR 404, 422 settings src/cluster_erp/modules/sales_orders/settings/services.py:28

Events emitted

The table lists the contract classes that code under src/cluster_erp/modules/sales_orders/ 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
SalesOrderCancelled 1 src/cluster_erp/modules/sales_orders/orders/services.py:737
SalesOrderClosed 1 src/cluster_erp/modules/sales_orders/orders/services.py:684
SalesOrderDelivered 2 src/cluster_erp/modules/sales_orders/orders/services.py:674
SalesOrderMatched 1 src/cluster_erp/modules/sales_orders/orders/services.py:451
SalesOrderMismatchDetected 1 src/cluster_erp/modules/sales_orders/orders/services.py:439
SalesOrderOpened 1 src/cluster_erp/modules/sales_orders/orders/services.py:635
SalesOrderPartiallyShipped 1 src/cluster_erp/modules/sales_orders/shipments/services.py:1371
SalesOrderPoReceived 2 src/cluster_erp/modules/sales_orders/orders/services.py:330
SalesOrderRevisionRequested 1 src/cluster_erp/modules/sales_orders/orders/services.py:487
SalesOrderShipped 2 src/cluster_erp/modules/sales_orders/orders/services.py:664

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

Verified against commit 92f8051 · 2026-11-13