Skip to main content

Commit Movement

POST 

/api/v2/inventory/movements/composer

Atomic commit of a composed movement: creates inventory adjustments, persists lot/serial detail, and triggers allocation release or demotion — all inside one DB transaction. When an outbound demotion consumes hard-allocated stock, each confirmed shipping label is voided in the same transaction (the fulfillment's inventory is reversed back to on-hand, its FulfillmentOrder budget reopened, and the shipment marked canceled).

Not yet available to API tokens

This endpoint currently requires session authentication; Personal Access Token scope support is in progress.

Named route: v2.inventory.movements.composer

Request fields:

  • direction (required) — one of: receive, ship, adjust_up, adjust_down

  • warehouse_id (required) — must exist in warehouses

  • movement_date (required) — ISO date

  • against_type (optional) — purchase_order, transfer, or none

  • against_id (optional) — ID of the source doc when against_type is set

  • reason (optional, max 1000 chars)

  • lines[] (required, min 1):

    • product_id (required)
    • quantity (required, non-zero whole number — positive for inbound, negative for outbound; a fraction is refused with 422)
    • unit_cost (optional, >= 0)
    • serials[] (optional, each max 100 chars)
    • lot (optional): lot_number, expires_at, manufactured_at
    • override_reason (optional, max 500 chars)
  • void_confirmations[] (required when preview-demotion returned requires_void_confirmation=true):

    • fulfillment_id (required)
    • attempt_void (required bool)
    • reason (optional, max 500 chars)

    A confirmation for a fulfillment that holds none of the stock this movement reduces is refused with 422 — remove it, or void that fulfillment from its own sales order.

Response shape (200):

{
"data": {
"adjustment_ids": [101, 102],
"voided_fulfillment_ids": [9001],
"skipped_fulfillments": []
},
"message": "Receipt committed — 1 line(s)."
}

voided_fulfillment_ids lists the fulfillments whose labels were voided. skipped_fulfillments lists any confirmed fulfillment that could not be voided (already voided, or part of a multi-shipment merge group) as { fulfillment_id, kind, reason } — these are skipped, not fatal.

Error (422): Returned when hard-allocated fulfillments are missing from void_confirmations or any other \InvalidArgumentException is thrown by the manager.

{ "error": "Hard-allocated fulfillment #9001 requires an explicit void confirmation before committing." }

release_backorders (boolean, inbound only, default true): when true, the received stock is applied to any waiting back-orders (promoting them to allocated); when false, the stock is received as free inventory and the back-orders keep waiting.

release_sales_order_ids (array of ints, inbound only, optional): granular release. Omit or null to release ALL waiting back-orders; pass a list of sales order ids to release only those orders' back-orders. Requires release_backorders = true.

created_lots — the lots this commit created, each with its fifo_layer_id and batch_number. Returned for inbound directions (receive, adjust_up) only; an outbound commit creates no lot and returns an empty array. Use it to attach a Certificate of Analysis to the lot after the movement is committed, via POST /api/v2/fifo-layers/{fifoLayer}/documents.

  • rechain_affected (optional bool, default false) — when the entry is dated earlier than existing consumption in an affected product/warehouse pool, opt in to re-anchor those later transactions to the oldest available stock (true FIFO) after the save commits. Runs as a background job; pools in a locked accounting period or with unsupported shapes are skipped and reported.

Serial numbers: for a serial-tracked product, a line may carry serials (one per unit moved). An empty list is accepted. A non-empty list must match the line quantity (for an inbound direction in Auto generation mode it may be shorter), must not repeat a serial, and on an inbound direction must not name a serial that already exists; on an outbound direction the Require exact match availability rules apply. Otherwise the request returns 422 with a message naming the serial.

Request​

Responses​

OK

Response Headers
    Content-Type