Create BOM
POST/api/manufacturing/boms
Create a new BOM with output lines, component lines, and (optional) operations.
manufacturing:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Consumption method fields:
default_consumption_method(optional, enum:forward_flush|backflush) — BOM-level default inherited by component lines that omit their ownconsumption_method. Null means no default (lines fall back toforward_flush).component_lines[].consumption_method(optional, enum:forward_flush|backflush) — how the component is issued when production is recorded.forward_flush(the default) waits for the operator to issue the component explicitly with an actual consumed quantity;backflushauto-consumes it from the produced output quantity multiplied by the BOM per-unit usage, with no operator entry required. An explicitnullbehaves exactly like omitting the field — the line inheritsdefault_consumption_method, falling back toforward_flushwhen the BOM has no default. The method is snapshotted onto each manufacturing-order component line at confirmation, so later BOM edits never change how an already-open order consumes.
Operation cost fields: each operations[] row accepts time_minutes, cost_per_hour, and fixed_cost (optional, numeric, min 0) — a flat per-run cost added on top of time-based labour. Fixed cost is capitalized onto finished goods the same way labour is, but is never marked up by work-center overhead.
Auth: requires Bearer token.
cost_classification (optional, labor|overhead, default labor) sets the expense classification independently of the rate basis: labor posts the operation's variable cost to the Labor bucket (marked up by the work center's overhead %); overhead posts machine/tooling-style cost to the Overhead bucket with no additional markup.
Validation: a component line's product_id may not equal the BOM's own product_id or any output_lines.*.product_id — a BOM cannot consume its own output as a component. Violations return 422 with an error on component_lines.{index}.product_id.
Units: uom_id is optional on every output and component line. When omitted, the line is measured in that line product's own stock unit, so a product stocked by weight, volume or length never needs a conversion it does not have. Send uom_id only to override that deliberately — it must be a unit enabled on the product, or the request is rejected with a 422 naming the unit and product.
Contractor-supplied components: set component_lines[].is_contractor_supplied to true when the contract manufacturer provides that component from their own stock. It stays in the recipe and in lot genealogy, but is never allocated from your inventory, never reported as short, and never costed into the finished good — its cost is already inside the contractor's price on the purchase order. Defaults to false; omit the key on an update and the stored value is left unchanged.
Request
Responses
- 201
- 401
- 403
- 422
- 429
Created
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Validation failed — the body is a field → messages map (Laravel shape) or the platform envelope with a stable machine-readable code. Fix the payload and resubmit.
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.