E129: Create work order
POST /api/work-orders
Opens a new work order to produce finished goods from materials and (optionally) sub-assembly SKUs. Triggered from the Work Orders page, "New WO". The workflow validates inputs, rolls up the material unit cost recursively through the BOM, snapshots the recipe into work_order_inputs so later BOM edits do not affect this WO, and writes the matching demand/order ledger entries when the initial status implies them.
Authentication
Standard tenant route. Requires Authorization: Bearer <firebase-id-token> and X-Org-Id: <org-id>. Access: Member.
Request
{
"skuId": "uuid",
"quantity": 100,
"siteLocationId": "uuid",
"stockLocationId": "uuid",
"startDate": "2026-05-18",
"expectedDate": "2026-05-25",
"notes": "..."
}
| Field | Type | Required | Notes |
|---|---|---|---|
skuId | uuid | yes | Must have a BOM. |
quantity | decimal | yes | Output quantity. |
siteLocationId | uuid | yes | Where production happens. |
stockLocationId | uuid | yes | Where finished goods land. |
startDate | date | yes | |
expectedDate | date | no |
Snapshots the SKU's current BOM into work_order_items (recipe snapshot per W129) — later BOM edits do not retroactively change this WO. woNumber is generated server-side (per-tenant numbering).
Response — 201 Created
{
"id": "uuid",
"woNumber": "WO-2026-0017",
"skuId": "uuid",
"quantity": 100,
"status": "Production",
"siteLocationId": "uuid",
"stockLocationId": "uuid",
"startDate": "2026-05-18",
"expectedDate": "2026-05-25",
"materialUnitCost": 4.12,
"conversionCost": 1.50,
"notes": "..."
}
Errors
| HTTP | code | Condition |
|---|---|---|
| 404 | not_found | SKU or location does not exist. |
| 422 | validation_failed | SKU has no BOM, or shape invalid. |
Workflow
Calls W129 Create work order.