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.

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

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.

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
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
{
  "locationId": "gid://shopify/Location/1234567890",
  "first": 100,
  "after": null
}
location-inventory-levels.response.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
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
{
  "inventoryItemId": "gid://shopify/InventoryItem/1111111111"
}
item-inventory-levels.response.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}]
          }
        ]
      }
    }
  }
}

Written by Lintel. MIT license: free to use in your own store and in client work.

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.
  • Validated against the Admin or Storefront API schema for version 2026-10 on the date shown. Check the version in your request URL.
  • IDs and store addresses in the examples are placeholders. Replace them with your own.
  • Admin API calls need an access token from your app. Never put an Admin API token in a storefront or theme.
  • MIT license. Use the code in your own store or in client work.

Need this built, tested and maintained for your store? See API integrations.

Have something to build? Let’s talk it through.

Taking a limited number of projects at a time. Every brief is read by an engineer, not a salesperson.

Gencer KarakayaShopify Engineer

An engineer reads your brief, and we reply by email.