# Manage inventory

> Set and read inventory for a Shoplazza product's variants across locations with the Open API, and see how inventory items and locations relate.

Set and read a product's inventory across your locations.

## When to use this

Stocking new products, restocking, or distributing stock across warehouses.

## Prerequisites

- A working public app with OAuth and token storage — follow [Develop a standalone app](/docs/app/getting-started/create-public-app/develop-app) first. Every request below carries an `Access-Token: {token}` header, using the token you saved for each shop.
- The `inventory` access scope granted during OAuth.

## How inventory is modeled

Inventory lives at the intersection of two things:

- A **location** — a warehouse or store that holds stock.
- An **inventory item** — the stockable unit behind a variant.

An **inventory level** - is the stock of one inventory item at one location. To set stock you need the variant's `inventory_item_id` and a `location_id`.

### Set inventory for a product's variants

Setting stock takes four steps: get the variant ids, resolve them to inventory items, pick a location, then set the level per item.

**1. Get the product's variant ids**

`GET /openapi/2026-01/products/{id}`

Response: the variant ids are under `data.data.product.variants[].id`. Full fields: see [Get product](/api/product-detail).

**2. Resolve each variant id to its `inventory_item_id`**

Array params must repeat the key: `variant_ids=a&variant_ids=b`.

`GET /openapi/2026-01/inventory_items/variant`

Response (excerpt, list under `data.data.variant_inventory_items`):

```json
{
  "code": "Success",
  "data": {
    "variant_inventory_items": [
      { "inventory_item_id": "626514004247984698", "variant_id": "28ea5ee4-5b1d-4a9d-a92e-e60f0dff3da8" }
    ]
  }
}
```

Full fields: see [List variant inventory items](/api/inventory-item-variants).

**3. Pick a location**

Reuse the location the product's stock already sits at.

`GET /openapi/2026-01/products/{id}/inventory`

Response (excerpt, location id under `data.data.variants[].location_items[].location_id`):

```json
{
  "code": "Success",
  "data": {
    "product_id": "4d3e7859-455c-4899-a296-7befe731c585",
    "Stock": 7,
    "variants": [
      {
        "variant_id": "28ea5ee4-5b1d-4a9d-a92e-e60f0dff3da8",
        "location_items": [{ "location_id": "604253696473177059", "stock": 3 }]
      }
    ]
  }
}
```

Full fields: see [Get product inventory](/api/product-inventory).

**4. Set the level for each inventory item**

`POST /openapi/2026-01/inventory_levels/set`

Request body:

```json5
{
  "inventory_item_id": "626514004247984698",
  "location_id": "604253696473177059", // 64-bit integer — send it as a string
  "stock": 100
}
```

Response (excerpt, updated level under `data.data.inventory_level`):

```json
{
  "code": "Success",
  "data": {
    "inventory_level": {
      "inventory_item_id": "626514004247984698",
      "location_id": "604253696473177059",
      "stock": 100,
      "updated_at": "2026-07-02T02:58:47Z"
    }
  }
}
```

:::warning
`location_id` is a 64-bit integer that exceeds JavaScript's safe integer range (for example `604253696473177100`). If you parse it as a JavaScript number it silently rounds and the set call fails with `Location not found`. Keep 64-bit ids as strings — parse the response with a big-int-aware parser, or send `location_id` as a string as shown above. (`inventory_item_id` comes back as a string already.)
:::

Full fields: see [Set inventory level](/api/inventory-level-set).

### Read a product's inventory

`GET /openapi/2026-01/products/{id}/inventory`

Response (excerpt):

```json
{
  "code": "Success",
  "data": {
    "product_id": "4d3e7859-455c-4899-a296-7befe731c585",
    "Stock": 7,
    "variants": [
      {
        "variant_id": "28ea5ee4-5b1d-4a9d-a92e-e60f0dff3da8",
        "location_items": [{ "location_id": "604253696473177059", "stock": 3 }]
      }
    ]
  }
}
```

Full fields: see [Get product inventory](/api/product-inventory).

### Work with locations

List locations, or get the default one, to choose where stock lives.

`GET /openapi/2026-01/locations/default`

Response: the default location object, under `data.data.location`. See [Get default location](/api/location-get-default).

To list all locations, change the default, deactivate one, or set priority, see [List locations](/api/locations), [Change default location](/api/location-change-default), [Deactivate location](/api/location-deactivate), and [Edit location priority](/api/location-edit-priority).

## Other inventory operations

For finer control, work with inventory items and levels directly. Read or update the item behind a variant, or list, create, update, and delete inventory levels one location at a time.

See [List inventory items](/api/inventory-items), [Get inventory item](/api/inventory-item), [Update inventory item](/api/inventory-item-update), and for levels: [List](/api/inventory-levels), [Create](/api/inventory-level-create), [Update](/api/inventory-level-update), and [Delete](/api/inventory-level-delete).

## Next steps

- [Create and update products](/docs/app/use-cases/product-merchandising/create-and-update-products)
- [Organize products into collections](/docs/app/use-cases/product-merchandising/organize-collections)
