---
title: "Adds or removes stock for an item at one location."
method: POST
path: "/api/v1/items/{id}/stock/adjust"
tags: ["Items"]
---

# Adds or removes stock for an item at one location.

`POST /api/v1/items/{id}/stock/adjust`

## Request

- Base URL: `https://app.flexonthejob.com`
- URL: `https://app.flexonthejob.com/api/v1/items/{id}/stock/adjust`
- Auth: HTTP bearer

Requires `ManageInventory` and an `Idempotency-Key` header. A positive
`delta` creates that many stock units at the location exactly like "Add inventory"
on the Items page (template properties, cost, barcodes copied); a negative `delta`
writes off the oldest available units the way "Delete" on the Inventory page does
(soft delete - restorable in the app, recorded in each unit's change history with
`reason`). Stock never goes negative here: removing more than is on hand answers
`409` and changes nothing. Units in transit on a transfer are never touched.
Omit `locationId` for the organization's "No Location" bucket. Misc items, parent
groups and sub-unit items hold no stock (`409`); job sites are refused (`422`).
Example: `{ "locationId": 3, "delta": -2, "reason": "Damaged in van" }`.

## Path parameters

- `id` integer, required

## Request body

- AdjustStockRequest: Body of `POST /api/v1/items/{id}/stock/adjust`: add or remove whole units of an item at one stock location. Example: `{ "locationId": 3, "delta": -2, "reason": "Damaged in van" }`.
  - `locationId` integer, nullable: Stock location the units are added to / removed from (see `GET /api/v1/locations`). Omit or null for the organization's "No Location" bucket. Job sites are refused (422).
  - `delta` integer: Whole units to add (positive) or remove (negative); never zero. Removal takes the oldest available units first and is refused with 409 when fewer are on hand than requested. Example: `5` receives five units, `-1` writes one off. At most 1000 units per call (each unit is a physical stock row); split larger changes into several calls.
  - `reason` string, nullable: Optional reason recorded in each unit's change history (e.g. `"Cycle count"`). Max 500 characters.

## Response `200`

Stock changed; body carries the confirmation and the item's updated per-location stock.

- StockChangeResponse: Result of a stock adjustment or move, with the item's stock position after the change.
  - `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, `delta` of zero, or missing `Idempotency-Key`.
- `401`: Unauthorized
- `403`: Forbidden
- `404`: No such active item in this organization.
- `409`: Not enough units at the location to remove, the item cannot hold stock, or the key's creator is unknown on this server.
- `422`: Unknown location, or the location is a job site.
- `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)
