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
- Get location IDs once from the locations query.
- Send StockAtLocation with first: 100 and page with after: endCursor until hasNextPage is false.
- Pick the states you need in names: available, on_hand, committed, incoming, reserved, damaged, safety_stock or quality_control.
- For a single SKU across warehouses, send StockOfItem with its inventory item ID.
Code
location-inventory-levels.graphqlquery 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.graphqlquery 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.
Shopify documentation
- 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.
