This year at Unite, we introduced Locations, which will be launching in coming months. We know that many of you are responding to this exciting update by updating your Shopify apps to support merchants with multi-location inventory.
In addition to Locations, we also announced the release of our new GraphQL Admin API. And while both these announcements are exciting, you’re busy— so what should you spend your limited RnD time on?
Well, why not both?
In this blog post, we’ll show you how dabbling in GraphQL can prepare your app to support users that manage inventory across multiple locations.
Updated August 31, 2018
To allow apps to sync inventory changes faster, we have just released a new
inventoryBulkAdjustQuantityAtLocation GraphQL mutation.
This mutation has a cost of 10, and allows to adjust the inventory of up to 100 inventory items at a specific location. With the GraphQL bucket refill of 50 this allows adjusting inventory of up to 500 inventory items per second.
With a sync bandwidth of 1.8M adjustments per hour, this should remove the need for Fulfillment Services to be the inventory manager; i.e. using the hourly
fetch_stock sync. We recommend this mutation as the prefered way for Fulfillment Services to sync inventory changes with Shopify.
The biggest questions around how to prepare for Locations
While the merchant release of Locations is yet to come, we opened a public beta of the features for all partners at Unite. Since that announcement, there have been a few questions I’ve heard repeatedly from partners participating in the beta:
- How do I use the new Inventory APIs to create product variants and assign their initial inventory?
- Using the new Inventory API requires my app to make more API calls—how do I get around that?
- Can I bulk update inventory levels?
Fortunately, our new GraphQL Admin API can help solve all of these issues. A common theme in all these questions—and a huge advantage of GraphQL—is the API call limit. It’s important to understand that our GraphQL API doesn’t have the same concept of a call limit like REST.
The limits of the GraphQL Admin API are based on a calculated cost for each individual query, and not on a set call limit like our REST API. Another important thing to note is that the REST Admin APIs and GraphQL Admin APIs can be used in conjunction (with individual call limits), as the only difference in using GraphQL is that your calls are directed to a new universal endpoint:
In this article, we’ll address those three above questions with the Inventory APIs using GraphQL, both to show you how to implement it, and to provide a guide to transition to the new Inventory APIs.
To properly follow this tutorial, you should have:
- The GraphiQL app installed on a Shopify store
- If you want to test the queries with multiple locations, a development store with location enabled
- An understanding of how to interact with the Shopify Admin API
- Knowledge of the upcoming API changes to support multiple locations
You might also like: Build Better Apps Faster with the New Admin API in GraphQL .
1. How do I use the new Inventory APIs to create product variants and assign their initial inventory?
First, we can look at an example of how to create a new product, and stock it at two different locations. In order to explore this further, we first need to know how to create new data in GraphQL using mutations. Check our documentation, or any of the publicly available resources for more info.
To create a new product, we’ll use the
productCreate mutation. For brevity, we’ll give our product a title, with a single variant that is stocked at two separate locations. To successfully run the mutation, we’ll need a
Product.title and the
locationID of both locations that we want to stock our new item.
locationID essentially tells Shopify where you want to stock that item. If you don’t know the
locationID of the location(s) where you want to stock the item, you would first need to run a GraphQL query to retrieve the active available Locations for that shop. A query with an entrypoint into locations would look something like this, depending on the data you want returned:
Now that we have the IDs of the locations where we want to stock the new items, we can jump right into the `createProduct` mutation example.
While this may seem complicated, it can be broken down into two parts. First, let’s look at the
productCreate mutation. In the mutation we are creating a product with only a `title` as it is simply a test product (but you can pass any of the details required for a product here). Secondly we are stocking this product’s single variant at the two `locationID`s from our initial query, and specifying that we want Shopify to track the inventory.
Note: If you don’t include the
inventoryManagement field, the mutation will succeed, but
inventoryManagement will default to ‘NOT MANAGED’, meaning that products inventory levels are not tracked/visible.
The second half of the call is a query to return the data that you just created. This functions identically to simply making query. Using the
createProduct mutation, we can specify the properties we want returned from our new Product object. In this case, we asked for the inventory levels at each Location by name to confirm the mutation did stock the item as requested.
Now that you’ve seen how to manage your variants, you are probably still concerned about the additional calls you will have to incorporate into your app’s flow. This brings us to our next most common question.
2. Using the new Inventory API requires my app to make more API calls—how do I get around that?
In a world where products were stocked only at a single Location, a single API call to retrieve or update inventory levels would suffice. It’s no wonder that in a world where multiple Locations can exist for a single item, multiple API calls would be required.
But what if I told you that a single GraphQL query can effectively manage inventory across multiple locations, without slowing down your app or requiring multiple API calls? Two of the greatest advantages of GraphQL is being able to query for only the specifics that you need, and traversing multiple resources in a single query that would require multiple REST calls.
As shown by this example, we are able to traverse the graph to gain a lot of information that would require multiple calls using the REST API, in one single GraphQL query. While not directly comparable to REST, this type of query actually has quite a low cost—see
The GraphQL leaky bucket is 1000 plus 50 per second, meaning you could make around 5 of these calls per second, and never run out. One of the benefits of GraphQL is that you can only request exactly what you need, so we can get the cost even lower by removing query fields if necessary.
Now let’s take the information from the above query and use it to adjust inventory at one of the locations. All we really need for the
inventoryAdjustQuantity mutation is an
inventoryLevelId, as this id refers to a specific inventory item at a specific location. We can punch that into our mutation from above and adjust the available inventory by 3:
And voila, we’ve adjusted the available inventory by three, return:
Now that we’ve updated a single inventory level, what about multiple levels in a single call to GraphQL?
3. Can I bulk update inventory levels?
Another benefit of GraphQL is that it is possible to send multiple mutations within a single HTTP request. This will not reduce the cost calculation, and there is no call limit in GraphQL, but it can reduce the latency of the updates.
In order to update inventory in bulk, we’ll need to know the
inventoryLevelId of each level we want to adjust. While the method we used above is great for finding a lot of information about a single variant, let’s take a look at how you could retrieve multiple inventory levels in a single query. While the information you are requesting can vary, a query will look something like this:
Here we are querying for inventory item
id and the
inventorylevels for the first 3 product variants on a store. The results will look like this:
Now that we have the IDs to work with, let’s update our initial mutation to work for multiple inventory levels. Note that while each of the results for the query are the same location, the below mutation does not require all of the items to be in the same location.
This uses an alias for each mutation, so the result of each mutation can be identified:
The return from this mutation will be:
The only gotcha here is that you need to name each of the individual requests in the mutation uniquely. In my example they are item1, item2, and item3.
Just the beginning
We’ve barely scratched the surface of what is possible with GraphQL. Hopefully this helps you get over the most common roadblocks in supporting Locations and multi-location inventory.
If there are any more specific examples you would like to explore, please post on our forums to get help!
Already used GraphQL Admin API for your apps? Let us know in the comments below!