This guide shows you how to use the GraphQL Admin API to sync and maintain accurate inventory quantities, and transition products to different inventory states. ## Requirements - Your app can make [authenticated requests](/docs/api/admin-graphql#authentication) to the GraphQL Admin API. - Your app has the `read_inventory` and `write_inventory` [access scopes](/docs/api/usage/access-scopes). Learn how to [configure your access scopes using Shopify CLI](/docs/apps/build/cli-for-apps/app-configuration). - Your store has existing [products](/docs/api/admin-graphql/latest/objects/Product). - You're familiar with the different [inventory states](/docs/apps/build/orders-fulfillment/inventory-management-apps#inventory-states). - You're using API version 2023-01 or higher. To [schedule changes to inventory quantities](#schedule-changes-to-inventory-quantities), you need to use API version 2024-01 or higher. ## Inventory object relationships Before you begin managing inventory quantities and states, it's helpful to understand the relationships between inventory objects. The following diagram illustrates the relationships between inventory objects in the GraphQL Admin API:
The relationships between inventory objects in the GraphQL Admin API.
| API object | Description | | ---------- | ---------- | | [ProductVariant](/docs/api/admin-graphql/latest/objects/ProductVariant) | Contains merchandising information, such as price, description, and images.

Think of this as the product information that you might want a customer to see. All product variants have a 1:1 relationship with their associated inventory item. | | [InventoryItem](/docs/api/admin-graphql/latest/objects/InventoryItem) | Contains information about the physical product, such as its SKU.

Think of this as the backend information used for managing inventory, shipping, and fulfillments. Inventory items are associated with one or many inventory levels. An inventory item has an inventory level for each location where the item is stocked. | | [InventoryLevel](/docs/api/admin-graphql/latest/objects/InventoryLevel) | The actual `quantities` of an item that are in a specific [inventory state](/docs/apps/build/orders-fulfillment/inventory-management-apps#inventory-states).

Inventory levels connect one inventory item to one location. Each inventory level holds the available quantity for its inventory item at the associated location. | | [Location](/docs/api/admin-graphql/latest/objects/Location) | A geographical location where a merchant does business, such as a retail store or warehouse.

Locations can have many inventory levels. Each location has one inventory level for each inventory item that the location stocks. | ## Step 1: Retrieve IDs for inventory locations and inventory items You can use the [`locations`](#locations-query) query to retrieve the IDs of inventory locations and inventory items. To retrieve inventory at fulfillment service app locations, you need to use the [`shop`](#shop-query) query instead of the `locations` query. An inventory level represents the quantities of an inventory item that's associated with a location. An inventory item represents the goods that are available to be shipped to a customer. You'll use the IDs for inventory levels and inventory items to query inventory quantities in [the next step](#step-2-query-inventory-quantities). ### `locations` query The following example shows how to retrieve the first three locations and their associated inventory levels. The response returns a set of parameterized global IDs. > Note: > The [`InventoryLevel`](/docs/api/admin-graphql/latest/objects/InventoryLevel) object has a global ID that contains parameters because the `InventoryLevel` object is associated with the [`InventoryItem`](/docs/api/admin-graphql/latest/objects/InventoryItem) object. > > For example, if the `InventoryLevel` object's ID is 69407473686 and the `InventoryItem` object's ID is 32889739542550, then the global ID resolves to the following structure: `gid://shopify/InventoryLevel/69407473686?inventory_item_id=32889739542550`.

### `shop` query The following example shows how to retrieve the first three fulfillment service app locations and their associated inventory levels. The response returns a set of parameterized global IDs.

## Step 2: Query inventory quantities You can use the following queries to retrieve inventory quantities: - [Query inventory quantities for an item at a specific location](#query-inventory-quantities-for-an-item-at-a-specific-location) - [Query inventory quantities for an item at multiple locations](#query-inventory-quantities-for-an-item-at-multiple-locations) ### Query inventory quantities for an item at a specific location You can use the [`inventoryLevel`](/docs/api/admin-graphql/latest/queries/inventoryLevel) query to retrieve inventory quantities for an item at a specific location. Each inventory level belongs to one inventory item and has one location. For every location where an inventory item can be stocked, there's an inventory level that represents the inventory item's quantities relating to that location. The following example query retrieves the quantity of an inventory item that's available at a specific location. The response shows 11 items that are available at the location.

### Query inventory quantities for an item at multiple locations You can use the [`inventoryItem`](/docs/api/admin-graphql/latest/queries/inventoryItem) query to retrieve inventory quantities for an item at multiple locations. The following example query retrieves the quantity of an inventory item that are available, on-hand, reserved, and committed at the first five locations. The response shows 72 available items, 101 on-hand items, 0 reserved items, and 29 committed items at the locations.

## Step 3: Manage inventory quantities You can use the following mutations to manage inventory quantities: - [Set inventory quantities on hand](#set-inventory-quantities-on-hand): Explicitly set the quantity of inventory that's in the `available` or `on-hand` state. - [Adjust inventory quantities](#adjust-inventory-quantities): Add or remove quantities of inventory that are in the `available` state. - [Move inventory quantities between states](#move-inventory-quantities-between-states): Transition inventory quantities between the `available` state and the `reserved`, `damaged`, `safety_stock`, and `quality_control` states, or between unavailable states (`reserved`, `damaged`, `safety_stock`, and `quality_control`). - [Schedule changes to inventory quantities](#schedule-changes-to-inventory-quantities): Create a scheduled change that states the dates associated with upcoming changes to inventory quantities. > Note: > You can't use the Admin API to adjust or move inventory quantities in the `committed` state. Inventory quantities in the `committed` state are only affected by the creation and fulfillment of a merchant's orders. ### Set inventory quantities on hand The `on_hand` state represents the total number of units that are physically stocked at a location. The `on_hand` state equals the sum of inventory quantities in the following states: You set inventory in the `on_hand` state to maintain an accurate count of physical inventory. For example, you might need to set inventory in the `on_hand` state in the following scenarios: - Inventory was received outside of a purchase order - A stocktake was completed and inventory needs to be adjusted accordingly You can use the [`inventorySetQuantities`](/docs/api/admin-graphql/latest/mutations/inventorySetQuantities) mutation to set available and on-hand inventory quantities at a location to a given value. In the `reason` field in the mutation's input, you can specify one of the following reasons for adjusting inventory quantities: | Reason | Description | | --- | --- | | `correction` | Used to correct an inventory error or as a general adjustment reason. | | `cycle_count_available` | Used to specify an adjusted inventory count due to a discrepancy between the actual inventory quantity and previously recorded inventory quantity. | | `damaged` | Used to remove units from inventory count due to damage. | | `movement_created` | Used to specify that an inventory transfer or a purchase order has been created. | | `movement_updated` | Used to specify that an inventory transfer or a purchase order has been updated. | | `movement_received` | Used to specify that an inventory transfer or a purchase order has been received. | | `movement_canceled` | Used to specify that an inventory transfer or a purchase order has been canceled. | | `other` | Used to specify an alternate reason for the inventory adjustment. | | `promotion` | Used to remove units from inventory count due to a promotion or donation. | | `quality_control` | Used to specify that on-hand units that aren't sellable because they're currently in inspection for quality purposes. | | `received` | Used to specify inventory that the merchant received. | | `reservation_created` | Used to reserve, or temporarily set aside unavailable units. | | `reservation_deleted` | Used to remove the number of unavailable units that have been reserved. | | `reservation_updated` | Used to update the number of unavailable units that have been reserved. | | `restock` | Used to add a returned unit back to available inventory so the unit can be resold. | | `safety_stock` | Used to specify that on-hand units are being set aside to help guard against overselling. | | `shrinkage` | Used when actual inventory levels are less than recorded due to theft or loss. | The following example shows how to set the on-hand inventory quantity to 102. The response shows the delta of incrementing the on-hand inventory quantity by 1 because the previous inventory count in the `on_hand` state was 101.

### Adjust inventory quantities You can use the [`inventoryAdjustQuantities`](/docs/api/admin-graphql/latest/mutations/inventoryAdjustQuantities) mutation to increment or decrement the total amount of inventory that's in the `available`, `damaged`, `quality_control`, `reserved`, or `safety_stock` state at a location. For example, a merchant might need to adjust inventory quantities in the following cases: | State that needs adjustments | Use cases | | --- | --- | | `available` |