# Read stock levels by location

> Read available, on hand, committed and incoming stock for every item at a location, or for one item across all locations.

Page: https://lintelagency.com/resources/graphql/inventory-levels-by-location

## In short

To read stock per location, query location(id) and page through its inventoryLevels, asking each level for quantities(names: ["available", "on_hand", "committed", "incoming"]). To see one item everywhere, query inventoryItem(id) and its inventoryLevels, which returns one level per location. The quantities field replaces the old available count and returns every inventory state you ask for.

## Facts

- **API:** Admin GraphQL API
- **Operations:** location, inventoryItem (inventoryLevels, quantities)
- **Access scopes:** read_inventory, read_locations
- **Replaces (REST):** GET /admin/api/inventory_levels.json?location_ids=…
- **API version:** 2026-10
- **Last checked:** 2 November 2026

## How to use it

1. Get location IDs once from the locations query.
2. Send StockAtLocation with first: 100 and page with after: endCursor until hasNextPage is false.
3. Pick the states you need in names: available, on_hand, committed, incoming, reserved, damaged, safety_stock or quality_control.
4. For a single SKU across warehouses, send StockOfItem with its inventory item ID.

## Code

### location-inventory-levels.graphql

```graphql
query StockAtLocation($locationId: ID!, $first: Int!, $after: String) {
  location(id: $locationId) {
    id
    name
    inventoryLevels(first: $first, after: $after) {
      nodes {
        item {
          id
          sku
        }
        quantities(names: ["available", "on_hand", "committed", "incoming"]) {
          name
          quantity
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}
```

### location-inventory-levels.variables.json

```json
{
  "locationId": "gid://shopify/Location/1234567890",
  "first": 100,
  "after": null
}
```

### location-inventory-levels.response.json

```json
{
  "data": {
    "location": {
      "id": "gid://shopify/Location/1234567890",
      "name": "Main warehouse",
      "inventoryLevels": {
        "nodes": [
          {
            "item": {"id": "gid://shopify/InventoryItem/1111111111", "sku": "LS-S"},
            "quantities": [
              {"name": "available", "quantity": 12},
              {"name": "on_hand", "quantity": 15},
              {"name": "committed", "quantity": 3},
              {"name": "incoming", "quantity": 20}
            ]
          }
        ],
        "pageInfo": {
          "hasNextPage": true,
          "endCursor": "eyJsYXN0X2lkIjoxMTExMTExMTExfQ=="
        }
      }
    }
  }
}
```

### item-inventory-levels.graphql

```graphql
query StockOfItem($inventoryItemId: ID!) {
  inventoryItem(id: $inventoryItemId) {
    id
    sku
    tracked
    inventoryLevels(first: 20) {
      nodes {
        location {
          id
          name
        }
        quantities(names: ["available", "on_hand"]) {
          name
          quantity
        }
      }
    }
  }
}
```

### item-inventory-levels.variables.json

```json
{
  "inventoryItemId": "gid://shopify/InventoryItem/1111111111"
}
```

### item-inventory-levels.response.json

```json
{
  "data": {
    "inventoryItem": {
      "id": "gid://shopify/InventoryItem/1111111111",
      "sku": "LS-S",
      "tracked": true,
      "inventoryLevels": {
        "nodes": [
          {
            "location": {"id": "gid://shopify/Location/1234567890", "name": "Main warehouse"},
            "quantities": [{"name": "available", "quantity": 12}, {"name": "on_hand", "quantity": 15}]
          },
          {
            "location": {"id": "gid://shopify/Location/1234567891", "name": "Shop floor"},
            "quantities": [{"name": "available", "quantity": 2}, {"name": "on_hand", "quantity": 2}]
          }
        ]
      }
    }
  }
}
```

## Limits and edge cases

- Inactive levels are left out unless you pass includeInactive: true.
- on_hand is available plus committed and the unavailable states; incoming is stock on its way, not yet on hand.
- For a full stock export across thousands of items, run the same query as a bulk operation.

## Questions

### How do I get inventory for a specific location in Shopify?

Query location(id) { inventoryLevels(first: 100) { nodes { item { sku } quantities(names: ["available"]) { quantity } } } } and page through the results.

### What is the difference between available and on hand?

available is what can be sold now. on_hand is everything physically there, including units already committed to orders and units set aside as damaged or reserved.

### Why is inventoryLevel.available missing?

It was replaced by quantities(names: [...]), which returns any inventory state by name.

## Shopify documentation

- [InventoryLevel object](https://shopify.dev/docs/api/admin-graphql/latest/objects/InventoryLevel)
- [Inventory states](https://shopify.dev/docs/apps/build/orders-fulfillment/inventory-management-apps/manage-quantities-states)

## Related

- [Set stock levels from an external system](https://lintelagency.com/resources/graphql/set-inventory-quantities)
- [Page through results with cursors](https://lintelagency.com/resources/graphql/cursor-pagination)
- [Keeping inventory in sync with another system](https://lintelagency.com/journal/sync-inventory-external-system)

License: MIT. Free to use in your own store and in client work.
