---
title: "Applies several stock adjustments and moves in one call, all or nothing."
method: POST
path: "/api/v1/items/stock/batch"
tags: ["Items"]
---

# Applies several stock adjustments and moves in one call, all or nothing.

`POST /api/v1/items/stock/batch`

## Request

- Base URL: `https://app.flexonthejob.com`
- URL: `https://app.flexonthejob.com/api/v1/items/stock/batch`
- Auth: HTTP bearer

Requires `ManageInventory` and an `Idempotency-Key` header (one key covers the
whole batch). Each operation follows the rules of `POST /api/v1/items/{id}/stock/adjust`
(`"action": "Adjust"`) or `/stock/move` (`"action": "Move"`). Operations apply
in order, so a later removal can use units an earlier one added. Every operation is checked
before anything is written, and the writes share one transaction: if any operation fails,
nothing changes and the problem's `detail` starts with `operations[i]` naming the first
failing one (also in the `failedIndex` extension). 1..100 operations, at most 1000 units in total.
Example: <c>{ "operations": [ { "action": "Adjust", "itemId": 12, "locationId": 3, "delta": 10 },
{ "action": "Move", "itemId": 12, "fromLocationId": 3, "toLocationId": 4, "quantity": 2 } ] }</c>.

## Request body

- StockBatchRequest: Body of `POST /api/v1/items/stock/batch`: several adjustments and moves applied in order, all or nothing. Example: <c>{ "operations": [ { "action": "Adjust", "itemId": 12, "locationId": 3, "delta": 10, "reason": "Delivery" }, { "action": "Move", "itemId": 12, "fromLocationId": 3, "toLocationId": 4, "quantity": 2 } ] }</c>.
  - `operations` StockBatchEntry[], required: 1..100 operations, applied in the order given. At most 1000 units in total across the batch.
    - `action` 'Adjust' | 'Move', required: What one entry of a stock batch does.
    - `itemId` integer: Numeric item id (see `GET /api/v1/items`). Example: `12`.
    - `locationId` integer, nullable: `Adjust` only: the stock location adjusted. Omit or null for the organization's "No Location" bucket.
    - `delta` integer, nullable: `Adjust` only: whole units to add (positive) or remove (negative), never zero, -1000..1000. Example: `-2`.
    - `fromLocationId` integer, nullable: `Move` only: location the units leave. Required for a move.
    - `toLocationId` integer, nullable: `Move` only: location the units arrive at. Omit or null for "No Location".
    - `quantity` integer, nullable: `Move` only: whole units to move, 1..1000. Example: `3`.
    - `reason` string, nullable: Optional reason recorded in each affected unit's change history. Max 500 characters.

## Response `200`

Every operation applied; one result per operation with the item's stock after the batch.

- StockBatchResponse: Result of `POST /api/v1/items/stock/batch`: one entry per operation, in request order.
  - `message` string: Human-readable confirmation, e.g. `Applied 2 stock operation(s).`
  - `results` StockChangeResponse[]: Per operation: the same shape as a single adjust/move response, with the item's stock after the whole batch.
    - `itemId` integer: The item (template) whose stock changed.
    - `message` string: Human-readable confirmation, e.g. `Moved 3 x 'Widget' from 'Main' to 'Van 2'.`
    - `units` integer: Whole units added, removed or moved (always positive).
    - `locationId` integer: For an adjustment: the location adjusted. For a move: the source location.
    - `locationName` string: Name of LocationId.
    - `destinationLocationId` integer, nullable: For a move: the destination location; null for an adjustment.
    - `destinationLocationName` string, nullable: Name of DestinationLocationId; null for an adjustment.
    - `stock` StockSummary: Stock position of an item.
      - `onHand` number, double: Total on hand; same semantics as `onHand`.
      - `byLocation` LocationStock[]: Per-location breakdown of physical rows. Sums to the row count, which may differ from OnHand for oversold or sub-unit items.
        - `locationId` integer: Location id.
        - `locationName` string: Location name.
        - `quantity` integer: Whole item rows at the location (not deleted, not in a job site).

## Other responses

- `400`: Malformed body, empty or oversized batch, an operation missing its `delta`/`quantity`, or missing `Idempotency-Key`.
- `401`: Unauthorized
- `403`: Forbidden
- `404`: An operation names no active item in this organization.
- `409`: Not enough units for an operation, an item that cannot hold stock, or the key's creator is unknown on this server.
- `422`: Unknown location, a job site, source equal to destination, or too many units in total.
- `429`: Too Many Requests

---

[API](https://skmtc.dev/flexonthejob/apis/flex-api.md) · [All operations](https://skmtc.dev/flexonthejob/apis/flex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/flexonthejob/apis/flex-api/revisions/19c8f4d27acf?raw)
