# Set a product's absolute stock level at one outlet

PUT https://api.oletapp.com/your-store/v1/products/{id}/inventory/{outlet_id}

Loop-safe: the delta is computed server-side from the current level under a row lock, so sending the same `on_hand` twice writes nothing the second time (`changed: false`).

- A supplied `reason_id` must match the computed direction, or leave it out to use the system "Stock set via API" reason.
- `Idempotency-Key` is optional here: the write is already idempotent by construction.

- `422 REASON_DIRECTION_MISMATCH`: the supplied `reason_id` does not match the computed direction.
- `422 REASON_NOT_ALLOWED`: the supplied `reason_id` is a system reason or is turned off. A reason must be enabled and must not be a system reason.
- `422 OUTLET_DELETED`: the outlet has been deleted.

`unit_cost` (integer cents, optional) becomes the average cost for the outlet, whether stock goes up, down or stays the same. Leave it out to keep the current average, or the supply price when there is no average yet.

**Requires scope:** `inventory:write`

Required scope: `inventory:write`

## Parameters

| Name | In | Type | Required |
|---|---|---|---|
| `id` | path | string | yes |
| `outlet_id` | path | string | yes |

## Request body

```
{
  note?: string | null
  on_hand: number
  reason_id?: string
  unit_cost?: integer | null
}
```

## Response (200)

```
{
  data: {
  adjustment_id: string | null
  changed: boolean
  delta: number
  movement_id: string | null
  on_hand: number
  previous: number
}
}
```

Errors follow the standard error envelope: https://getolet.com/resources/developers/errors.md

## Example

```bash
curl -X PUT "https://api.oletapp.com/your-store/v1/products/{id}/inventory/{outlet_id}" \
  -H "Authorization: Bearer olet_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"on_hand":0}'
```
