d
Topic
Ryan O Shopify Employee
Posts:
233
Last edited 3 months ago

Updated Deadline: Aug 1st -- [Deprecation] Important changes to ProductVariant, Refund and Fulfillment APIs

UPDATE SEP 14 

Hey Devs!

We've recently shipped a new change to help with identifying calls that we consider deprecated.  We've added a new header to return on these calls:

X-Shopify-API-Deprecated-Reason

If you receive one of these headers in your response, this means Shopify considers that a deprecated call.  This is an effort to allow these calls to be machine readable, and loggable, in order to assist developers in identifying the areas that need to be updated.

Examples of calls that will return this header:

  • Creating a fulfillment without a location
  • Creating a product with variants that have "inventory_quantity"
  • Creating a new variant on a product that has "inventory_quantity"
  • Updating a variant with "inventory_quantity_adjustment"
  • Updating a variant with "inventory_quantity"

 

Happy Coding!

 

UPDATE JUNE 28: 

Hey Devs,

Just want to let you know that we are extending the deprecation deadline from July 1st to August 1st.  There will be a new post tomorrow with more details, but we just wanted to get it out there to maybe relieve some of the stress you are feeling headed into the weekend.

Most, if not all of your questions will be answered in the post tomorrow so try to save any queries for that!

Cheers All!

Ryan

 

Hey Devs,

Shopify is preparing to release multi-location inventory features to all merchants this summer. All apps that create fulfillments or manage inventory will need to be updated by July 1st, 2018, to remain functional on shops that track inventory across multiple locations.

Key dates

July 1st, 2018

  • Apps will no longer be able to create fulfillments without specifying a location
  • Apps will no longer be able to set inventory on the Product/Variant APIs

Migrating to support multi-location fulfillments

Shopify fulfillments are currently “location unaware”, meaning that when an app creates a fulfillment and fulfills an order, Shopify decrements the inventory with no concept of which location that inventory should be decremented from. In order to support merchants with inventory allocated across multiple locations, apps will need to include a location_id when creating fulfillments.

For details on how to migrate your apps to support multi-location, see our Multi-Location Fulfillment Migration Guide.

Migrating to support multi-location inventory

Currently inventory is set and adjusted on the product variant and is not tracked by any particular location. In anticipation of multi-location inventory, Shopify has released a new Inventory API, which includes two new endpoints: Inventory Item and Inventory Level. The Inventory API will allows apps to effectively manage inventory quantities across multiple locations.

For details on how to migrate your apps to support multi-location inventory, see our Multi-Location Inventory Migration Guide.

We’ll keep you up to date as we continue to make improvements to our platform’s multi-location fulfillment and inventory management capabilities, so you can continue to build the best apps to help extend these new features.

If you have any questions about this change, please read our detailed FAQ or contact deprecations@shopify.com.

 

Thanks,

Shopify Apps Team

i
Replies
tomn68 Member
Posts:
1
8 months ago
g
1
upvotes

Is this a revised schedule? I thought the last email from February where it stated May 7 as option to enabled multi-location inventory and then Jan 1 2019 where it goes read only.

Just so I'm clear, if we use the product variant to track inventory levels but do not use them to track muli-location inventory levels, does this new July 1st date effect us in this use case?

 

Tom

Posts:
12
8 months ago

Hi Ryan,

It would be a lot better if you guys could allow us to enable multi location on our development stores before releasing this nice addition to the grand public. 

We are authoring an inventory management platform with a nice integration with Shopify. This is a very important change we need to get right from the start and we don't have much time left. 

Another question which came up from our engineering team is: how are existing merchands who don't have multi-location enabled going to be affected? Will the deprecated inventory APIs be disabled for this merchands cohort as well? 

 

Thanks in advance.

Tahar from Stock&Buy

Ryan O Shopify Employee
Posts:
233
8 months ago

Hi Tahar, 

Stay tuned for details on enabling multi-location features on development shops.  I don't have any public details to share except that it will be available to all partner developers before it launches to merchants.

 

For all,

If you have specific implementation questions for the migration please contact deprecations@shopify.com.

Posts:
12
8 months ago

Thanks Ryan. Appreciate the super fast response. 

By the way, we did send an email to deprecations@shopify.com but received no response :)

Posts:
4
8 months ago

Hello, after reading the post i realized that for the FulfillmentApi the only change that's need is to provide a location_id.

The question is: where do i find the location_id? I mean no location has been specified right now for products and variants, so how can they be associated to a Location? Is this something that happens by default for all the inventory?

Thanks!

Ryan O Shopify Employee
Posts:
233
8 months ago

Hi Ralph,

There is no change to the orders API.  If you specified inventory_behaviordecrement_obeying_policy Shopify will handle all of the inventory decrementing using the new APIs.

 

Hi Fabio,

You can get the location_id from https://help.shopify.com/api/reference/location#index to see them all or from https://help.shopify.com/api/reference/inventorylevel to see locations for a specific item.

 

Ryan

Posts:
14
Last edited 8 months ago
g
2
upvotes

Hello Ryan O,

Two issues with this:

1. This change violates the golden API rule.. once publised, behaviour should not change or break. Why not allow us to continue setting variant -> inventory_quantity and under the hood just update the appropriate inventory item/level for the default Location?

2. This change will incur extra API calls.

 

Upon further review...

(a) https://help.shopify.com/api/tutorials/inventory-migration-guide#affected-apis
Affected API | Changing behaviour 

Setting inventory_quantity will adjust a product variant's inventory at its location that has the lowest ID. The inventory at that location will be adjusted so that the sum of inventory across all locations matches the value set by inventory_quantity. Use the Inventory Level endpoint instead.

(b) https://help.shopify.com/api/tutorials/inventory-migration-guide#deprecation-schedule
Deprecation Schedule

July 1, 2018
Apps will no longer be able to set inventory_quantity or inventory_quantity_adjustment on the product variant.

(a) and (b) seem to contradict each other or does "Setting inventory_quantity.." refer to current behaviour?

 

Thanks,
Paul

Posts:
20
Last edited 8 months ago
g
2
upvotes

So with a new shop where you have to add lets say 100 product calls to the api, you now have to add that x times for each variant due to the inventory level getting its own endpoint ? Isn't it possible to just send the inventory items with the variants within the same call for when you add a new product with variants ?

Metafields is a myth...
Hari Member
Posts:
6
7 months ago
g
1
upvotes

Hi,

I use a private app (not Third party apps) to make API calls to my store endpoint to update inventory quantity and fulfillment details for the order. fulfillment_service is set to "manual" for all the products/variants. I fulfill the products manually and use my custom application to update Shopify with the required details.

Question:

1. Is location_id still mandatory in the fulfillment API even when private apps are making the call to create the fulfillment records ?

2. When the product is set to fulfillment_service = manual, can i update the inventory levels using Inventory API without specifying the location_id.

bardia Member
Posts:
11
Last edited 7 months ago

Hi Ryan,

Could you please update the post's links to the two Migration tutorials? They point to 404.

Thanks,

Bardia

Robert Tolton Member
Posts:
9
Last edited 7 months ago
g
1
upvotes

@Hari - I too would like to know this, I have a private app performing fulfillments currently. It's slightly concerning that neither the fulfillment migration tutorial nor the API docs for locations are currently available? Is locations something you opt-in to?

Ryan O Shopify Employee
Posts:
233
7 months ago

Hey All,

Fulfillment Migration Guide, Locations, if these don't work for you, try resetting your cache.  The  URLs were only down for about 30 minutes for the migration to the new developers site.

Question:

1. Is location_id still mandatory in the fulfillment API even when private apps are making the call to create the fulfillment records ?

2. When the product is set to fulfillment_service = manual, can i update the inventory levels using Inventory API without specifying the location_id.

You must always include a location ID, doesn't matter about private apps.

Posts:
57
Last edited 7 months ago
g
1
upvotes

I noticed the same thing as Paul and mentioned it here. Important to get an answer. 

Ryan O Shopify Employee
Posts:
233
7 months ago

Responded to your other thread as well:

 

You have to include a location ID even if the shop only has a single location.  The changed behaviour on Product and Product Variant went into place when that document was pubished in late 2017, and will only continue to take place in a grace period for grandfathered apps after the release of multiple locations.  This is in order to mitigate the affect on merchant's inventory if the apps do not migrate in time.  I will update the migration guide to be more clear about this.

Posts:
12
Last edited 7 months ago
g
1
upvotes

Hi Ryan,

We are still unclear about how the new API will work. Here are a few issues / questions we are currently having a very hard time with:

  1. Is multi location equivalent to multiple locations? What I mean is, we have a test store with three locations but the has_multilocation flag is still set to false. Is there a place in the admin area where we can turn this on? Can one define multiple POS locations with the has_multilocation flag set to false? 
  2. Related to point 1 above, do you have an ETA as to when we can we set the multi location flag?   

I would be helpful if you can answer these questions in a timely manner, we have one engineer staying idle waiting for these points to be clarified :)

Thank you in advance.

Tahar.

Ryan O Shopify Employee
Posts:
233
7 months ago

You can test the multi-location feature by creating a new development store from your partner account and checking the box here:

Once your store is created you can go to settings > locations and enable the features.

For 1.  Even with the flag off, you may have more than one location.  This could be from POS locations, or automatically created from a fulfillment service

Posts:
12
7 months ago

Thanks a lot Ryan. That definitely helps. In case of a store with multiple POS locations and the has_multi_location flag set to false, how will Shopify behave? Would inventory and orders be handled same as if the multi-location flag was set?  

Again thanks for all the clarifications.

Posts:
57
7 months ago

Hi Ryan O. Here is another question. When creating a product via the API or creating a new variant via the API do we, in essence have to create variants with zero inventory and then after the call completes we set inventory levels for the necessary location(s)? So the new flow of product creation would be:

  1. Setup JSON for a full product including properties, images, variants, metafields, etc...
  2. POST to /admin/products.json
  3. Inspect response JSON to get inventory item ID's
  4. For each variant's inventory_item_id, submit a POST to inventory_levels/set.json to set its available inventory

This right? Make sense? No way to create a product with inventory levels in one call anymore?

Andrii Member
Posts:
2
7 months ago

Hi Ryan,

Can you help me, I have a method that set inventory_quantity. The question is: what should I do now? Do you have some tutorial what to do in this case? For now I haven't any locations for my application.

Thanks, Andrii.

Ryan O Shopify Employee
Posts:
233
Last edited 7 months ago

Andrii, check out the inventory migration guide in the original post.  You will need to convert to the new inventory APIs.

Andrii Member
Posts:
2
Last edited 7 months ago

Ryan, I read it, but I can't understand how to do it. Should I manually create location level record for each variant?

Also this link is not correct maybe (https://help.shopify.com/api/reference/location)?

Ryan O Shopify Employee
Posts:
233
7 months ago

I'm not sure I understand your question Andrii, and this forum isn't the best platform for 1:1 support.  Could you email deprecations@shopify.com and add some more details to your request.  Thanks!

Posts:
57
7 months ago

Hi all, this change is tough on developers. I would actually suggest talking this out here would be great! 

Ryan O Shopify Employee
Posts:
233
7 months ago
g
1
upvotes

So the new flow of product creation would be:

  1. Setup JSON for a full product including properties, images, variants, metafields, etc...
  2. POST to /admin/products.json
  3. Inspect response JSON to get inventory item ID's
  4. For each variant's inventory_item_id, submit a POST to inventory_levels/set.json to set its available inventory

This right? Make sense? No way to create a product with inventory levels in one call anymore?

This is correct.

Hi all, this change is tough on developers. I would actually suggest talking this out here would be great! 

The email is handled by a whole team, and can help with specific shops, request-ids, and other private data.  General questions are fine here though.

Ryan O Shopify Employee
Posts:
233
Last edited 7 months ago

Thanks a lot Ryan. That definitely helps. In case of a store with multiple POS locations and the has_multi_location flag set to false, how will Shopify behave? Would inventory and orders be handled same as if the multi-location flag was set?  

Again thanks for all the clarifications.

When the merchant opts in to multiple locations (aka enabling the flag), this allows the merchant to create new locations, and automatically connects all of their existing inventory to the shipping origin location.  All other behavior is already implemented and functioning currently.

Ryan O Shopify Employee
Posts:
233
7 months ago

Paul,

1. This change violates the golden API rule.. once publised, behaviour should not change or break. Why not allow us to continue setting variant -> inventory_quantity and under the hood just update the appropriate inventory item/level for the default Location?

2. This change will incur extra API calls.

1. This is why we gave as long of a lead time as possible, we recognize that this is a large change for developers and will continue to work with you to get it done.

2.  If your apps are having issues being rate limited due to the new multi-location features, please reach out to deprecations@shopify.com and we can discuss your individual use-cases.

Upon further review... (a) and (b) seem to contradict each other or does "Setting inventory_quantity.." refer to current behaviour?

The wording has since been updated to clarify: "The following behaviors are temporary and exist only to help you migrate to the Inventory API. Updating inventory using the Product and ProductVariant APIs is deprecated, and should no longer be relied upon to update inventory."

 

Poul,

So with a new shop where you have to add lets say 100 product calls to the api, you now have to add that x times for each variant due to the inventory level getting its own endpoint ? Isn't it possible to just send the inventory items with the variants within the same call for when you add a new product with variants ?

In order to set the inventory level on a new inventory item, yes you will need to make another call.  You cannot set the inventory level in the same call as creating the variant.

Posts:
12
7 months ago

Hi Ryan,

Thanks a lot for all the help and insights you gave us so far. While performing our final acceptance tests, we found out that the `location_id` attribute of the order object is always set to `null` and instead, it is the fulfillement object which now holds the location from where the order is fulfilled. 

Will the `location_id` attribute of the order object be deprecated? 

Thanks in advance,

Kind regards,

Tahar

Posts:
14
Last edited 6 months ago

Thank you Ryan,

I just noticed that SKU will also need special handling, incurring even more calls. The Product Variant API guide doesn't have SKU marked as deprecated fwiw.

Paul

Posts:
57
6 months ago

Hey Paul,

Can you explain what you're seeing in more detail?

Posts:
14
6 months ago
g
1
upvotes
Posts:
71
Last edited 6 months ago

Hey Ryan,

After 1st July, for a shop that does not enable multi-location inventory, will each variant of the shop linked to an inventory_item? Or inventory_item only present if a shop has multi-location inventory enabled?

EDIT:
It looks like all variants will have an inventory_item :) irregardless multi-location inventory is enabled or not.

 

SimplyCost - Add costs and track profit (https://apps.shopify.com/simplycost)
Ryan O Shopify Employee
Posts:
233
6 months ago

Thanks a lot for all the help and insights you gave us so far. While performing our final acceptance tests, we found out that the `location_id` attribute of the order object is always set to `null` and instead, it is the fulfillement object which now holds the location from where the order is fulfilled. 

Will the `location_id` attribute of the order object be deprecated? 

Location_id on the order only exists if the order was made through a Shopify POS location.  These multi-location changes do not affect the Order API (this location_id was already there).

I just noticed that SKU will also need special handling, incurring even more calls. The Product Variant API guide doesn't have SKU marked as deprecated fwiw.

SKU will still be readable from the variant, but not writeable.  I'll look into a doc update for clarity.

After 1st July, for a shop that does not enable multi-location inventory, will each variant of the shop linked to an inventory_item? Or inventory_item only present if a shop has multi-location inventory enabled?

EDIT:
It looks like all variants will have an inventory_item :) irregardless multi-location inventory is enabled or not.

Inventory Items and Inventory Levels have been released and implemented since February.  All inventory logic has been using them since then, and yes they are useable without multi-location enabled.

Liam Hennessy Member
Posts:
3
6 months ago

Will the Liquid template variable variant.inventory_quantity be affected by this change?

Ryan O Shopify Employee
Posts:
233
6 months ago

Will the Liquid template variable variant.inventory_quantity be affected by this change?

There are no liquid updates planned for the initial release of multi-location.

Conner Member
Posts:
8
6 months ago

Hi,

Will I be able to set the availability for multiple inventory_levels at once? The documentation seems to show that we'll only be able to set the availability of one inventory_level at one time.

If so, this will dramatically increase the amount of API calls we have to make. Previously, we were adjusting inventory at the Product-level (which only included the VariantID and InventoryQty) to help reduce the number of API calls we have to make.

Thanks

Ryan O Shopify Employee
Posts:
233
6 months ago
g
1
upvotes

With the REST API, the only way to update multiple inventory levels in one call is by registering as a FulfillmentService and registering to be polled for inventory levels.

Using the new GraphQL Admin API however, you can easily update multiple inventory level in a single call (GraphQL doesn't use the concept of calls for rate limiting).  Example:

mutation {
  item1: inventoryAdjustQuantity (input: {inventoryLevelId: "gid://shopify/InventoryLevel/37685843?inventory_item_id=40011829139", availableDelta:3 }) {
    inventoryLevel {
      available
    }
    userErrors {
      field
      message
    }
  }
  
  item2: inventoryAdjustQuantity (input: {inventoryLevelId: "gid://shopify/InventoryLevel/37685843?inventory_item_id=40011857683", availableDelta:3 }) {
    inventoryLevel {
      available
    }
    userErrors {
      field
      message
    }
  }
  
  item3: inventoryAdjustQuantity (input: {inventoryLevelId: "gid://shopify/InventoryLevel/37685843?inventory_item_id=40011857875", availableDelta:3 }) {
    inventoryLevel {
      available
    }
    userErrors {
      field
      message
    }
  }
}

 

Posts:
3
6 months ago

Hi,

1) What impact will it have on products for which inventory is not tracking?

2) How to fulfill orders with such products? We didn’t set up a FulfillmentService. It looks the only way, in this case, is fetch available locations and use one of them to set a location_id for the fulfillment?
Suppose we will set up a FulfillmentService soon, but if we are not on the schedule, need a way to create fulfillments.
 

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

1) What impact will it have on products for which inventory is not tracking?

The inventory item will still have a location_id but will have available = null

example from my store:

{
  "inventory_levels": [
     {
        "inventory_item_id": 871696400403,
        "location_id": 13968900152,
        "available": null,
        "updated_at": "2018-05-22T14:50:57-04:00"
     }
  ]
}

 

2) How to fulfill orders with such products? We didn’t set up a FulfillmentService. It looks the only way, in this case, is fetch available locations and use one of them to set a location_id for the fulfillment?

You can still create a fufillment without registering as a fulfillment service, and pass the required location_id parameter.

Conner Member
Posts:
8
6 months ago

Ryan,

Thank you for the response.

Will inventory_quantity remain as a field within Variants-- just as read-only? Or should I expect to get all inventory information from the Inventory API going forward?

Thanks!

Ryan O Shopify Employee
Posts:
233
6 months ago

Yes inventory_quantity will remain on product variant as a read-only property.  It will reflect the sum of inventory available at all locations.

Posts:
12
6 months ago

Hi Ryan,

We have finished our move to the new inventory APIs.

We followed the documented upgrade checklist published on the Multi location API page and while the changes worked for most of our customers, these badly failing (HTTP 422) for a few other ones (they are super upset at us right now :) )

We have emailed the details of the failure to Shopify support, ticket ID: 9347019

Would you be able to help us on this please?

Thank you in advance,

Ryan O Shopify Employee
Posts:
233
6 months ago

Tahar,

Took a quick look, the inventory item you are trying to update is assigned to a fulfillment service for managing it's inventory.  When an item is set to use a fulfillment service, only that FS can update the inventory.

Posts:
12
6 months ago

Hi Ryan,

This is a major breaking change - we have many customers relying on us to update their inventory whome we will no longer be able to support :(

It is said in the documentation that setting inventory for an item managed by a fulfillement service should work fine as long as Shopify is instructed to disconnect if necessary. 

Again, this is major breaking change for us from a finantial perspective as we need to let go of all customers relying on fulfillment services. It is also a major breaking change for our customers as they need to find other ways of managing their inventory before July 1st.

Can you please double check this and get back to us so we can plan accordingly?  

 

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

I'm not really sure what actions you are trying to do here, is this a fulfillment service you have created and you are trying to manage the inventory?  Or is this a pre-existing fulfillment service that you do not manage?

EDIT: You are also including both relocate_if_necessary and disconnect_if_necessary in your call, these properties are for different endpoints, depending on what you are trying to do, one of these is incorrect.

Posts:
12
Last edited 6 months ago

We are an inventory management app (we are not a fulfillement service) - most of our customers own two to six stores all using the same inventory. Our app keeps the inventory of all stores in sync at all times. The issue reported above is from one of our customers for whome we are failing to keep his stores in sync as we get 422 errors whenever we try to update the stock levels. 

EDIT: You are also including both relocate_if_necessary and disconnect_if_necessary in your call, these properties are for different endpoints, depending on what you are trying to do, one of these is incorrect.

 

We are trying to set the available inventory at a given location, which flag should we use? 

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

See above edit, if you are just setting inventory with POST /admin/inventory_levels/set.json then you shouldn't include relocate_if_necessary as that is only for POST /admin/inventory_levels/connect.json as per the documentation.

Posts:
12
6 months ago

See above edit, if you are just setting inventory with POST /admin/inventory_levels/set.json then you shouldn't include relocate_if_necessary as that is only for POST /admin/inventory_levels/connect.json as per the documentation.

We tried this and we are still getting 422 errors. Probably because the stock level at that location can only be changed by the fulfillement service it is tied to? 

 

Ryan O Shopify Employee
Posts:
233
6 months ago

You also need to specify the location of the fulfillment service as the location_id.  If you can't get that to work, send a copy of your X-Request-Id header in with the ticket and I'll make sure it's looked at.  

Posts:
12
6 months ago

Hi Ryan,

Sorry for the late reply. 

You also need to specify the location of the fulfillment service as the location_id.

Yes, we do send the location ID as part of the inventory level payload. 
An important point I forgot to mention is that this works just fine for other stores with fulfillement services attached so we can definitely update stock level of product variants attached to third party fulfillement services. It is just the one (and few other stores from other customers) reported in the ticket which is failing for obscure reasons. 

 

Ryan O Shopify Employee
Posts:
233
6 months ago

Thanks Tahar, this seems like it would be best continued through your support ticket.  It's been escalated to technical support who can look into the specifics of the store and why it may not be working.  As much information as you can add to the ticket will help them greatly.

 

Cheers!

Posts:
57
Last edited 6 months ago

Hi again. I'm just looking for a confirmation on something. We will still be able to create a variant with a SKU correct? Updating it requires the inventory_item endpoint but we can create a product_variant with a SKU populated in one call still?

Ryan O Shopify Employee
Posts:
233
6 months ago

Current implementation allows the creation or editing of SKU on both the product variant AND the inventory item.  Upon updating either of them, shopify will update the other to match, so they will be in sync.

Posts:
57
6 months ago

By "current implementation" you mean right now, however on July 1st this will no longer be the case? The docs here say:

Loren D Member
Posts:
9
6 months ago

Will there be a 'count' endpoint for the inventory_levels?  The GET /admin/inventory_levels.json has 'page' and 'limit' properties, but they aren't very useful if I don't know the 'count' of items.

 

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

By "current implementation" you mean right now, however on July 1st this will no longer be the case? The docs here say:

We haven't yet removed the ability to set SKU on product creation using the REST API.  And this is not planned to be removed on July 1st, but I wouldn't consider it a permanent solution.

You could however, set SKU on product creation using the GraphQL Admin API (and update it's inventory in the same call), quick example below, working on a more detailed post about it;

 

mutation {
  productCreate(input: {title: "Test Product", variants: [
    {
      inventoryQuantities: 
      [
        {locationId: "gid://shopify/Location/13968900152", availableQuantity: 5},
        {locationId: "gid://shopify/Location/13969457208", availableQuantity: 10}
      ],
      inventoryManagement: SHOPIFY,
      sku: "TestSKU"
    }
  ]})
  {
  product{
    id
    variants(first:10) {
      edges{
        node{
          id
          sku
          inventoryItem{
            id
            inventoryLevels(first:10){
              edges {
                node
                {
                  id
                  available
                  location{
                    name
                    id
                  }
                }
              }
            }
          }
        }
      }
    }
  }
	userErrors {
      field
      message
  }
  }
}

 

Posts:
57
6 months ago

How about **updating** SKU using Rest API on the product_variant endpoint? Will that be supported after July 1st?

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

Will there be a 'count' endpoint for the inventory_levels?  The GET /admin/inventory_levels.json has 'page' and 'limit' properties, but they aren't very useful if I don't know the 'count' of items.

There are no plans for a count endpoint

How about **updating** SKU using Rest API on the product_variant endpoint? Will that be supported after July 1st?

Writing the sku field whether it is updating or initially setting it, will not be removed on July 1st.  You can however consider it deprecated, as we've released the "new and better" way to handle it.

Posts:
57
6 months ago

Ok thanks. Ryan, I really appreciate all the answers/guidance here. I think I can speak for all developers when I say this change is really rough and we are just trying to get our apps into a state where they won't break. We can then work on optimizing them further to use latest/greatest techniques to make them as efficient as possible.

Ryan O Shopify Employee
Posts:
233
6 months ago

No problem Jonathan!  We fully realize that this is tough, it is easily the largest change Shopify has ever made to our APIs so we are right here with you to help the transition!

Naren Member
Posts:
32
6 months ago
g
1
upvotes

Ryan

inventory_quantity on Variant API docs shows as deprecated. See attached screenshot

1. Can you confirm that "reading" inventory_quantity via Variant API is NOT deprecated?

2. Please clarify whether there are any plans to deprecate "reading" inventory_quantity via Variant API and the deprecation timeline in that case. 

If the API documentation can be updated to make this clear it would clear the confusion.

Thanks!

 

 

Inventory quantity on variant api shows deprecated thumb
Posts:
618
6 months ago

Will read_inventory and read_locations be backfilled for existing installations that already have the read_product scope?

Ryan O Shopify Employee
Posts:
233
Last edited 6 months ago

1. Can you confirm that "reading" inventory_quantity via Variant API is NOTdeprecated?

2. Please clarify whether there are any plans to deprecate "reading" inventory_quantity via Variant API and the deprecation timeline in that case. 

On the variant, inventory_quantity is being moved to read-only and there is no plan to remove that functionality.  This should only be used if you want an aggregate count of inventory at all locations, as it will not provide location specific details.

Will read_inventory and read_locations be backfilled for existing installations that already have the read_product scope?

We are handling these requests at deprecations@shopify.com.  If you would like us to backfill any permissions required for multi-location support to your existing installs, email us with the app details, and the permissions you want applied.  We'll confirm the details and respond before the backfill goes out so you know the date.

 

Ryan

 

Posts:
618
6 months ago

Ok, thanks Ryan.

Loren D Member
Posts:
9
6 months ago

Ryan, can you provide an example of using the GraphQL to retreive all of the available inventory for a given product?  I'm trying to get the available quantity for all of the variants associated with a given product, and can't find the correct syntax to query this.  The query below works for just the Product, but I need to get all of the variant inventories below that level. 

query {
  product(id: "gid://shopify/Product/94810538000") {
   variants {
    inventoryItems {
     inventoryLevels (first:10) {
        edges {
          node {
            location {
              name
                     }
           available
               }
              }
                                }
                   }
                   }
  }
  }

 

Ryan O Shopify Employee
Posts:
233
6 months ago
g
1
upvotes

Hi Loren, you're looking for something like this, +/- the info you need or don't need 

{
  product(id: "gid://shopify/Product/94810538000") {
    id
    variants (first:10) {
      edges {
        node {
          id
          inventoryItem {
            id
            inventoryLevels (first:6) {
              edges {
                node {
                  id
                  available
                  location {
                    id
                    name
                    address {
                      address1
                      address2
                      city
                      country
                      zip
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

 

Loren D Member
Posts:
9
6 months ago

Thanks - that works perfectly.  But how'd you generate that so fast?

 

Ryan O Shopify Employee
Posts:
233
6 months ago
g
1
upvotes

Practice!

Posts:
4
6 months ago

Hi Ryan,

For the fulfillment service API, how will i know which location_id i need to use for each line item? 

Right now my company uses a private app to do all our fulfillments and we have about 600 different fufillment service. 

Some of our order's come with a origin_location attached with the line item but some order's do not have it. how will i be able to fufill the line item if it does not come with an origin_location?

thanks.

Posts:
2
Last edited 6 months ago

Hi Ryan,

Do we need access to the locations API if we are just setting the inventory levels?  I'm trying to figure out how to query the levels and set their quantities but I'm a bit confused by the guide.

Do we need a location_id and an inventory Item id to adjust an inventory level?

Thanks

Ryan O Shopify Employee
Posts:
233
6 months ago

Hi Ryan,

For the fulfillment service API, how will i know which location_id i need to use for each line item? 

Right now my company uses a private app to do all our fulfillments and we have about 600 different fufillment service. 

Some of our order's come with a origin_location attached with the line item but some order's do not have it. how will i be able to fufill the line item if it does not come with an origin_location?

thanks.

Hi Mark, what is the use case behind 600 fulfillment services? 

When an item is assigned to a fulfillment service, an order will contain a property for `fulfillment_service` with the name of the fulfillment service responsible for that line item.  All fulfillment services have a ` location_id` assigned to them, which is what you should use.

Do we need access to the locations API if we are just setting the inventory levels?  I'm trying to figure out how to query the levels and set their quantities but I'm a bit confused by the guide.

Do we need a location_id and an inventory Item id to adjust an inventory level?

Thanks

If you want to query the `locations.json` endpoint you will need the read_locations.  For some more examples and details check out the migration guide for inventory and fulfillment

Posts:
2
6 months ago

Hi Ryan,

Thanks for the response, Im assuming you need to query locations to update an inventory level since 
https://help.shopify.com/api/reference/inventory/inventorylevel#adjust takes an inventory_item_id and a location_id? 

We don't really need to do anything with locations at all, but I don't see how we adjust inventory levels without it.

Thanks

Ryan O Shopify Employee
Posts:
233
6 months ago
g
1
upvotes

For your use-case you will need it!

Radhesh V. Member
Posts:
5
6 months ago

Hello,

I want to adjust multiple inventory_levels (around 300-400) in single GraphQL mutation query call, is there a way to do so? I tried adjusting 400 inventory levels using GraphQL App, but it showed " TypeError: NetworkError when attempting to fetch resource. " error to me. Is this error due to adjusting large number inventory levels at a time or weather am i missing something.

Thanks in advance.

Ryan O Shopify Employee
Posts:
233
6 months ago

New blog post How the New GraphQL Admin API Can Help You Manage Inventory and Locations.

 

 

I want to adjust multiple inventory_levels (around 300-400) in single GraphQL mutation query call, is there a way to do so? I tried adjusting 400 inventory levels using GraphQL App, but it showed " TypeError: NetworkError when attempting to fetch resource. " error to me. Is this error due to adjusting large number inventory levels at a time or weather am i missing something.

 

Radesh, you will want to look into how the call limit works for GraphQL.  That mutation would be too large.  I think the limit would be 200 inventoryAdjustQuantity mutations at one time.

Hari Member
Posts:
6
6 months ago

Hi Ryan,

We are using a Private app to update the inventory levels from our warehouse using Inventory set.json API. We noticed that once we update the inventory using the seet.json API, "Fulfillment service" value for the Product/variant changes to the Fulfillment service associated with the location_id.

Is this expected ? 

We are using Fulfillment service = Manual right now for all the products and we update inventory quantity only for certain products. 

 

Thanks,

Hari

 

Ryan O Shopify Employee
Posts:
233
6 months ago

Hi Hari,

Is the location_id you are passing in the inventory_levels set, the location_id of a fulfillment service? If so then yes this is intended.  This is because you are adding stock to that fulfillment service location.

Hari Member
Posts:
6
6 months ago

Yes Ryan. location id is tied to a fulfillment service.

Can we use any a location id that is not tied to a fulfillment service for inventory SET ?

Will Fulfillment service stay as Manual in this case ?

Also, for some the SKUs we are receiving 403 forbidden though all the information are accurate.

Ryan O Shopify Employee
Posts:
233
6 months ago

I believe setting inventory to be stocked at a fulfillment service location, means that inventory is now fulfilled by that location which is why you are seeing it change.  Setting inventory to a location that is not a fulfillment service will not change the fulfillment service off of manual.

For the SKU issue, its probably if the item is stocked at a fulfillment service already, in that case you have to include disconnect_if_true, to remove it from it's current location and connect it to the location specified in your call.

bardia Member
Posts:
11
Last edited 6 months ago

Is this a bug or intended and not documented?

When doing `POST /admin/inventory_levels/set.json` if the location_id belongs to a fulfillment_service the endpoint returns 422 without any error message even if you pass `disconnect_if_necessary: true`

Now if you try to circumvent this and do `POST /admin/inventory_levels/connect.json` to the fulfillment_service location_id and the product variant has a blank `SKU` then good luck figuring out the 422 response from the endpoint with an empty body(relocate_if_necessary: true is passed in). I stumbled upon the requirement when trying to set the fulfillment service through the dashboard.

UPDATE: setting the product's fulfillment_service through PUT products/variants/<id.json> actually returns

{
  "errors": {
    "sku": [
      "can't be blank"
    ]
  }
}

 

Can you guys make `POST /admin/inventory_levels/set.json` actually honor the `disconnect_if_necessary: true` so that an application doesn't have to call `connect.json` first.

 

 

 

 

Hari Member
Posts:
6
6 months ago

Hi Ryan,

We are setting disconnect_if_necessary to true for all the set.json calls. Even if that flag set, Shopify is returns 403 or 422 randomly.

We created a new product with some inventory in the screen and inventory levels GET call shows the item is randomly assigned location_id = 1809842203 which doesn't exist when we lookup using GET location calls.

Then when we tried to set the inventory qty using set.json it throws 403 forbidden even when disconnect_if_necessary to true.

Is there any reason why the new product is assigned to a random location_id after creation ?

 

Posts:
1
6 months ago

Our POST to Fulfillment have suddenly stopped working with the error "Required parameter missing or invalid".  I addeed location ID (our site doesn't have any defined fulfillment services, but when I call the Get for locations I do get one location and that's the ID I'm using).  

Here's the body I'm sending:

{"fulfillment": {"location_id": 15293071, "tracking_number":"9405510200882755885011","notify_customer": true, "line_items": [ { "id": 1261297664109, "quantity": 1 },{ "id": 1261297696877, "quantity": 1 }]}} 

what's the missing/invalid?

Radhesh V. Member
Posts:
5
6 months ago

Hola Ryan,

I even tried with 200 inventory adjustment but it results the same error. Then I tried with only 14 inventory adjustment, it showed me the same.

But when I tried multiple times with 11 adjustment values, it showed me unreliable results, like, it results proper output while some time shows "TypeError: NetworkError when attempting to fetch resource." error again.

Even there is no issue regarding call cost. Below is the call cost value for 10 adjustment for your reference.

 

 "extensions": {
    "cost": {
      "requestedQueryCost": 50,
      "actualQueryCost": 50,
      "throttleStatus": {
        "maximumAvailable": 1000,
        "currentlyAvailable": 950,
        "restoreRate": 50
      }
    }
  }

 

 

Thanks in advance.

Posts:
4
6 months ago

Hi Ryan

Thanks for the advice

Hi Mark, what is the use case behind 600 fulfillment services? 

We have vendor's listing their product on our site and each vendor we assigned a fufillment service so they could revieve emails of when their product was fufilled. We have started to change this model but we still need to support the old products until the end of the year.

When an item is assigned to a fulfillment service, an order will contain a property for `fulfillment_service` with the name of the fulfillment service responsible for that line item.  All fulfillment services have a ` location_id` assigned to them, which is what you should 

 

line_items:[
  {
    ..
    "fulfillment_service": "xihe",
    ..
  }
]

I saw the fufillment service is just a name, so does that mean that i will need to search through the locations based on the name and find the location_id

Robert Tolton Member
Posts:
9
Last edited 6 months ago

So, if my shop has "multi_location_enabled" set to false, confirmed by querying the "shop" endpoint - is there any action I need to take? This seems unclear.

From what I understand, for my POST requests to create Fulfillments, I need to add a "location_id" - but the only locations my shop has (found by querying the "locations" endpoint) are Point-Of-Sale iPad locations. (I'm guessing these are meant to be "legacy" locations now, but their "legacy" properties are false).

What should I be setting "location_id" to on my requests..??

-EDIT-

I'm seeing a "primary_location_id" - is this what I should be using? Is this property even mentioned in the documentation anywhere?

Also, the migration guide URL at the top of this page is still broken:
https://help.shopify.com/api/reference/shipping_and_fulfillment/fulfillment#create

Posts:
4
6 months ago

Hi Ryan, 

I am still unsure if my fulfillment service is set to manual, which location_id should i use. I can't seem to find the answer for this in any of the documentation. Not sure is it because i am missing something or am unable to understand.

 

Thanks

Posts:
3
6 months ago

Hi Ryan,

I've done the /admin/inventory_levels/set.json POST through php with json data, and I'm receiving an error message:

{"errors":{"inventory_item_id":"Required parameter missing or invalid"}}

I've sent inventory_item_id in the json string.  I got the inventory_item_id from the product api call in the variants section of the return.

What could be the problem here?

Posts:
12
6 months ago

Hi Ryan,

First of all, I am sorry to come back to this forum again, you must be drowning in different questions the developper community is bring up every day. 

We have been in touch with a couple of Shopify developpers and they reported an issue on Shopify side which is causing the inventory level updates to either fail with 422 error or reset the product filfillement services to Manual. 

The Shopify developpers confirmed that you guys are looking into these issues. Can you please let us know if the July 1st deprecation deadline will still apply even if these issues aren't fixed? 

Thanks in advance and again, sorry for all the back and forth. 

Tahar

ngt500 Member
Posts:
2
Last edited 6 months ago
g
1
upvotes

To "ostalks Admin"

I had the same issue. I was sending my JSON POST via php curl.

I was first sending the encoded JSON like this:

{"inventory_levels":{"inventory_item_id":12345678901,"location_id":87654321,"available":100}}

Results: "{"errors":{"inventory_item_id":"Required parameter missing or invalid"}}"

I removed the "inventory_levels" from my request and now it works.

/admin/inventory_levels/set.json

{"inventory_item_id":"12345678901","location_id":"87654321","available":"100"}

I am using "manual" for fulfillment and the location_id is just the shopify store.

Posts:
3
Last edited 6 months ago

Hi Ryan,

According to the document https://help.shopify.com/api/getting-started/authentication/oauth/scopes the app needs read_locations scope to have access to the locations resource. 

But I have tested with several stores that the app can read location with these scopes: write_products, read_products, write_orders, read_orders, write_shipping, read_shipping but without read_locations scope.

{
    "access_scopes": [
        {
            "handle": "write_products"
        },
        {
            "handle": "write_orders"
        },
        {
            "handle": "write_shipping"
        },
        {
            "handle": "read_products"
        },
        {
            "handle": "read_orders"
        },
        {
            "handle": "read_shipping"
        }
    ]
}

Since we need to know the location id to create fulfillment we need to have access to location resource. 
Should we update the access scopes for the app by adding read_locations or not because the app has access to it already?

Thanks,

Yuriy
 

Ryan O Shopify Employee
Posts:
233
6 months ago

Hey all, I'll try to answer what I can.  We definitely know there is a need for some better error messaging as inventory can have a lot of edge cases so good error messaging is key.

 

When doing `POST /admin/inventory_levels/set.json` if the location_id belongs to a fulfillment_service the endpoint returns 422 without any error message even if you pass `disconnect_if_necessary: true`

I've asked the team to look into this. looks like a bug.

 

We created a new product with some inventory in the screen and inventory levels GET call shows the item is randomly assigned location_id = 1809842203 which doesn't exist when we lookup using GET location calls.

Is there any reason why the new product is assigned to a random location_id after creation ?

There is currently some older shops that have inventory items assigned to deleted locations, there is work ongoing to fix this bad data. 

 

Then when we tried to set the inventory qty using set.json it throws 403 forbidden even when disconnect_if_necessary to true.

403 is returned if the item is active at a location (not a fulfillment service location) and set or connect is called for a different (not a fulfillment service location) and the shop is not multi-location. This happens regardless of any disconnect_if_necessay or relocate_if_necessaryflags. You won't see a 403 if you are dealing with a fulfillment service location. 

 

I even tried with 200 inventory adjustment but it results the same error. Then I tried with only 14 inventory adjustment, it showed me the same.

But when I tried multiple times with 11 adjustment values, it showed me unreliable results, like, it results proper output while some time shows "TypeError: NetworkError when attempting to fetch resource." error again.

There may be a size limit for requests, not entirely sure.  The good news is that there is no call limit besides the complexity costs, so you can simply make multiple calls of 10 mutations.

 

I saw the fufillment service is just a name, so does that mean that i will need to search through the locations based on the name and find the location_id

I would probably store these locally instead of fetching each time as they are unlikely to change often.  But yes, you would need to find the location_id associated to the service.

 

So, if my shop has "multi_location_enabled" set to false, confirmed by querying the "shop" endpoint - is there any action I need to take? This seems unclear.

From what I understand, for my POST requests to create Fulfillments, I need to add a "location_id" - but the only locations my shop has (found by querying the "locations" endpoint) are Point-Of-Sale iPad locations. (I'm guessing these are meant to be "legacy" locations now, but their "legacy" properties are false).

What should I be setting "location_id" to on my requests..??

-EDIT-

I'm seeing a "primary_location_id" - is this what I should be using? Is this property even mentioned in the documentation anywhere?

Also, the migration guide URL at the top of this page is still broken:
https://help.shopify.com/api/reference/shipping_and_fulfillment/fulfillment#create

Even without multi-location enabled you still need to migrate to use the new APIs.  Currently the only additional locations that a shop can have are POS locations, and fulfillment service locations.  The "legacy" property applies to fulfillment services only, not POS locations.  Your fulfillment should include the "location_id" that corresponds to the physical location you are shipping the item from.  "Primary_location_id" on the shop.json is a property that will always return the "location_id" of the 'Shipping Origin' which is a setting in the Shopify admin under shipping.  This is the address used to calculate the default shipping rates.  URL has been fixed.

 

I am still unsure if my fulfillment service is set to manual, which location_id should i use. I can't seem to find the answer for this in any of the documentation. Not sure is it because i am missing something or am unable to understand.

If an app is creating a fulfillment, the "location_id" you provide in the fulfillment should be the physical location that the goods are being fulfilled from.  If it is being provided by a 3rd party service, you pass the "location_id" of that fulfillment service.

 

I've done the /admin/inventory_levels/set.json POST through php with json data, and I'm receiving an error message:

{"errors":{"inventory_item_id":"Required parameter missing or invalid"}}

I've sent inventory_item_id in the json string.  I got the inventory_item_id from the product api call in the variants section of the return.

As per the docs you need to pass all 3 of: inventory_item_id, location_id, available. Another developer posted a solution above as well!

 

First of all, I am sorry to come back to this forum again, you must be drowning in different questions the developper community is bring up every day. 

We have been in touch with a couple of Shopify developpers and they reported an issue on Shopify side which is causing the inventory level updates to either fail with 422 error or reset the product filfillement services to Manual. 

The Shopify developpers confirmed that you guys are looking into these issues. Can you please let us know if the July 1st deprecation deadline will still apply even if these issues aren't fixed? 

Thanks in advance and again, sorry for all the back and forth. 

No problem, we realize this is as big of a migration for app developers as it is for us.  We will have more information to share soon on these issues.  Thanks for the patience!

 

Since we need to know the location id to create fulfillment we need to have access to location resource. 
Should we update the access scopes for the app by adding read_location or not because the app has access to it already?

We are currently not enforcing the need to have "read_locations" in order to query the `locations.json` endpoint to ease in migration.  This will be required in the future, so yes you should add it.

 

Happy coding!

Posts:
2
Last edited 6 months ago

Ryan,

I have some questions on edge cases:

1. If we're POSTing a fulfillment without any line items (in order to fulfill the entire order), do we need to fetch the individual line items from the order and create a different fulfillment for each item? During testing, we tried POSTing a fulfillment using mixed items with mutually exclusive locations, but only specifying a single location_id, and received this error: 

"{"errors":{"line_items":["must be stocked at the same location"]}}"

To me, this suggests we can no longer POST a fulfillment without line items if any items have mutually exclusive locations. Is this accurate?

2. Using an Order with a single item having quantity = 2, when we POST a partial fulfillment (quantity = 1) and specify a location A that has 0 quantity allocated, it appears that Shopify reallocates inventory levels at specified location A so that inventory level = -2. Further, the admin UI won't let us remove this item from location A because "Unfulfilled orders assigned to this location need inventory from this location." Is this the desired behavior? I was under the impression that going forwards items, not orders, are assigned to locations?

3. Right now we can POST fulfillments using location_ids with no stock, resulting in negative stock at that location. Will this functionality be in place after July 1st or are we currently in a grace period? Will we need to make sure that locations have stock available in order to POST fulfillments using that location_id?

Thanks, and appreciate all the hard work!

Posts:
3
6 months ago

Hi Ngt500,

Thanks,

I actually did it as you described here, but it still doesn't work, I even used the curl statement directly:

curl -X POST -k -H -i 'https://apikey:apipassword@store.myshopify.com/admin/inventory_levels/set.json' --data '{"inventory_item_id":"<inventory item id>","location_id":"<location id>","available":"34"}'

It still puts out the error.  Do you have any suggestions I think I may be missing here?

ngt500 Member
Posts:
2
Last edited 6 months ago

To "ostalks Admin"

Here is a basic version of what my app does. It pulls data from a MySQL table and essentially creates the array and does the curl request all in the in the while loop. I have removed the sql code and while loop from the code below.  I would look in your code to make sure you are sending Content-Type and Content-Length header. Also are you rate limiting? From what i've seen above some error messages from the API are still buggy and might not be the right error.

$url           = "https://apikey:apipassword@store.myshopify.com/admin/inventory_levels/set.json";

$inventoryData = array("inventory_item_id" => $inventory_item_id, "location_id" => $location_id, "available" => $available);
$data          = json_encode($inventoryData);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json', 'Content-Length: ' . strlen($data)));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
if(curl_getinfo($ch, CURLINFO_HTTP_CODE)!='200')
{
    echo curl_getinfo($ch, CURLINFO_HTTP_CODE)."\n";
}


My API permission: (some permissions might not be required for your app)
Inventory
write_inventory, read_inventory

Locations
read_locations

Product information
read_product_listings, write_product_listings

Products, variants and collections
read_products, write_products

Also I subscribed on your demo store if you would like to email me instead.

Posts:
3
6 months ago

ngt500,

Thanks, that helped.  I was missing Content-type.  Now works.

Ben Member
Posts:
33
Last edited 6 months ago
g
1
upvotes

Robert, I'm looking for an answer on this as well. Did you learn anything new? My store is also not multi location enabled, and I fulfill manually.

 

Could someone please answer Robert and Hari's questions about private apps that fulfill manually and don't have multi location enabled? Does this change coming up on 7/1 still apply in those cases? I did find a location ID on our only fulfillment location and I tested this by adding a location_id to my request to the fulfillment API and it came back as "NotFound", presumably because the location_id field on our orders is set to NULL.

Robert Tolton Member
Posts:
9
6 months ago

Hi Ben,

No I haven't got an answer yet, though Ryan did reply - I still have no idea what I should be setting the location_id to of the requests that I make. I have no fulfillment locations, so I have no IDs...!

Loren D Member
Posts:
9
6 months ago

Ben & Robert - I'm also using a private app with no fulfillment services.  For my fulfillments, I'm using the Primary_Location_ID from the /admin/shop.json.  I can query the locations (/admin/locations.json) and confirm that the locations exists.

BJ Member
Posts:
2
Last edited 6 months ago

Hi Ryan,

My name is Bindu. I am new here. Trying to migrate to the new Inventory level API without any success. I use a private app to upload inventory. I  successfully retrieved the available quantity using the below endpoint.

"admin/inventory_levels.json?inventory_item_ids=1069369732&location_ids=19931407";

But POST is failing. It keep saying bad request. Couldn't figure out what am I doing wrong in here. Below are some details about my request.

Exception: {"The remote server returned an error: (400) Bad Request."}  

Endpoint:     "https://*****.myshopify.com/admin/inventory_levels/set.json"
Json : {{"location_id":19931407,"inventory_item_id":1069369732,"available":43,"disconnect_if_necessary":true}}    System.Text.StringBuilder
X-Request-ID:    "70d6c6e5-bad0-4290-a532-21890715fcc1" 

 

We have only few more days left to migrate to the new Inventory-level API and I am kind of stuck here. Any help would be greatly appreciated.   

Ryan O Shopify Employee
Posts:
233
6 months ago

Robert, I'm looking for an answer on this as well. Did you learn anything new? My store is also not multi location enabled, and I fulfill manually.

 

Could someone please answer Robert and Hari's questions about private apps that fulfill manually and don't have multi location enabled? Does this change coming up on 7/1 still apply in those cases? I did find a location ID on our only fulfillment location and I tested this by adding a location_id to my request to the fulfillment API and it came back as "NotFound", presumably because the location_id field on our orders is set to NULL.

Hi Ben,

No I haven't got an answer yet, though Ryan did reply - I still have no idea what I should be setting the location_id to of the requests that I make. I have no fulfillment locations, so I have no IDs...!

Ben & Robert - I'm also using a private app with no fulfillment services.  For my fulfillments, I'm using the Primary_Location_ID from the /admin/shop.json.  I can query the locations (/admin/locations.json) and confirm that the locations exists.

Some clarifications on this thread:

  • Yes Private apps will have to move to the new fulfillment API behaviours, these requirements are independent of multi-location being enabled. 
  • If you are creating a fulfillment using the API, you must include a location_id.  All shops will have at least one location and therefore a location_id.
  • Having multi-location enabled just allows merchants to create more than one location.

Whether you want to support merchants with multiple locations is up to you, and would have to be reflected in your app if you do.

 

Hi Ryan,

My name is Bindu. I am new here.

I believe someone from the team answered your support ticket already, there's a syntax error in the JSON you are sending!

Ben Member
Posts:
33
Last edited 5 months ago

Thank you for the reply, Ryan. So what should I do to ensure our orders will return a value in the location_id field? I presume that's the reason fulfilling orders using the API is returning a "NotFound" status code, since no orders have the location ID I'm sending in. 

EDIT: I found my issue. We have two Shopify stores, one designated as a "test" store. I was using the production location_id for the test store. I plugged in the correct ID and the fulfillment is working now.

Ben

Robert Tolton Member
Posts:
9
5 months ago

I'm still not sure - the only locations that the locations endpoint gives me are for POS iPad locations, neither of which I can use as the location_id of fulfillments?

Where can I get a location_id that will work? The primary_location_id of the shop?

Ben Member
Posts:
33
5 months ago

Hey Robert -

Did you query the shop.json endpoint? it would be [your store]/admin/shop.json.

Robert Tolton Member
Posts:
9
5 months ago

Hi Ben, indeed - that's where I can get the primary_location_id value from, is that what I should be using?

Ryan O Shopify Employee
Posts:
233
5 months ago
g
1
upvotes

So what should I do to ensure our orders will return a value in the location_id field?

Hey Ben, orders only have a location_id if it is made from a POS location.

I'm still not sure - the only locations that the locations endpoint gives me are for POS iPad locations, neither of which I can use as the location_id of fulfillments?

Where can I get a location_id that will work? The primary_location_id of the shop?

The primary_location_id will correspond to the shipping origin location which should work.  There is also no reason why a POS iPad location wouldn't work.  There is no distinction between a POS location and a manually created location.  Adding a location_id to a fulfillment is simply stating which physical location the product is being shipped from.  If that location is the same as a store with a POS, then use that location_id.  If it is a separate location (warehouse, etc) add a new location in the admin with that address, and use that location_id.

 

Ben Member
Posts:
33
5 months ago

The primary_location_id is what I used, yep. It seems to be working with my fulfillments in my "test" Shopify environment.

Robert Tolton Member
Posts:
9
5 months ago

Thanks for the confirmation guys!

Ryan O Shopify Employee
Posts:
233
5 months ago

Hey Devs,

Just want to let you know that we are extending the deprecation deadline from July 1st to August 1st.  There will be a new post tomorrow with more details, but we just wanted to get it out there to maybe relieve some of the stress you are feeling headed into the weekend.

Most, if not all of your questions will be answered in the post tomorrow so try to save any queries for that!

Cheers All!

Ryan

 

Adam Member
Posts:
2
5 months ago

Now that we have to do multiple calls to the API to update something simple like QTY information (example, create a product, then update inventory qty with a second call), is it possible using REST or GraphQL to do both in one call? I have a client that has multiple shops and in their case this will result in a minimum of 8 calls to update the same stock across all stores. Please let us know or an example. Thanks

Ryan O Shopify Employee
Posts:
233
5 months ago

Hey Adam,

GraphQL can definitely do this.  I actually wrote this blog post as a primer to developers looking to use GraphQL to manage inventory.

rplum Member
Posts:
6
5 months ago

Ryan,

I need some clarification on creating products with the new structure from teh inventory levels additions.

We are currently creating products using teh REST api calls.   It appears that we will have to first create the variations and get the inventory item ID before we can assign a sku, then attach the item to a location before we can set the inventory level. 

I see your blog post regarding using GQL to do this in one step, but I envision my final solution to use a combination of REST and QGL calls, and I'm not seeing any way to get teh pure IDs via QGL.   teh QGL id s seem to derive from the IDs   eg.

gid://shopify/ProductVariant/9002157375551
9002157375551  REST Variant ID

but can I count on this?  I see to recall reading somehwere that we shoudl NOT count on this. 

This has become more urgent today since a new store I tried to create products in gave me this error:

{"error":"Write requests to inventory_quantity and inventory_quantity_adjustment are no longer supported. Please use the Inventory Levels API."}

I thought we had until Aug 1 to resolve this.  I don't see this error on any other of our clients stores.

Take care,

Roy.

 

 

 

 

Ryan O Shopify Employee
Posts:
233
5 months ago

Hi Roy,

Looks like you have a few different questions...

It appears that we will have to first create the variations and get the inventory item ID before we can assign a sku, then attach the item to a location before we can set the inventory level. 

You can still create products that have a SKU in REST.  Variants will automatically be assigned to a location upon being created.

I see your blog post regarding using GQL to do this in one step, but I envision my final solution to use a combination of REST and QGL calls, and I'm not seeing any way to get teh pure IDs via QGL.   teh QGL id s seem to derive from the IDs   eg.

gid://shopify/ProductVariant/9002157375551
9002157375551  REST Variant ID

but can I count on this?  I see to recall reading somehwere that we shoudl NOT count on this. 

I don't know what you mean as pure IDs.  You should not try to infer the graphQL ID from the REST ID.  This will not always match.  You can retrieve the ID from either the REST of GraphQL API.  Do not count on the ID being the same.

This has become more urgent today since a new store I tried to create products in gave me this error:

{"error":"Write requests to inventory_quantity and inventory_quantity_adjustment are no longer supported. Please use the Inventory Levels API."}

I thought we had until Aug 1 to resolve this.  I don't see this error on any other of our clients stores.

New apps cannot make adjustments after July 1st.  Existing apps have until Aug 1.

 

rplum Member
Posts:
6
5 months ago

Ryan,

Thanks for your quick reply

re:  New apps cannot make adjustments after July 1st.  Existing apps have until Aug 1

So this means that we cannot add any new clients of our app until we have completed this conversion.

That's harsh.

re:

I don't know what you mean as pure IDs.  You should not try to infer the graphQL ID from the REST ID.  This will not always match.  You can retrieve the ID from either the REST of GraphQL API.  Do not count on the ID being the same.

The ID I refer to is the number only that I need to access the item via REST.  Currently the only way I can get both the ID  (call it the old ID or the REST ID )   and the GQL ID is via REST.   So if I end up creating products viat GQL, I will ber missing teh REST ID's,  which I will need to get and fill in.

take care,

Roy.

Ryan O Shopify Employee
Posts:
233
5 months ago

So this means that we cannot add any new clients of our app until we have completed this conversion.

That's harsh.

New clients can install an existing app still.  You would be able to use your current behaviour until Aug 1.

The ID I refer to is the number only that I need to access the item via REST.  Currently the only way I can get both the ID  (call it the old ID or the REST ID )   and the GQL ID is via REST.   So if I end up creating products viat GQL, I will ber missing teh REST ID's,  which I will need to get and fill in.

Ah.  Yes the only way to get the GraphQL ID and the REST ID in the same call is using the REST API.

rplum Member
Posts:
6
5 months ago

Ryan,

We are a private app, and we are getting the aforementioned error now when trying to create products, so what you have said regarding existing behavior is not true at least for this particular new client's store.  It woudl appear that we are closed off from selling to new clients until I can get this working.

I am frantically tryiing to create products on a dev site using GQL, but I am stuck on creating variants with option values.  I dont seem to be able to fanthom how the docs on the various objects translate to queries or mutations.  

I am using the GraphQL app on the my dev store to try to work out what queries and mutations I will need.  I have created products and assigned inventory.  I am currently stuck on creating the option names at the product level and option values at the variant level.

Any help is greatly apreciated !!

 

Take care,

Roy.

 

rplum Member
Posts:
6
5 months ago

Ryan,

succesfully written GQL mutatiosnto create my products.  Now I "just" need to encode that method into my app.

I would also like to say that it appears there is no way to directly set an inventory level to a specfic qty using GQL.   Tt appears that this can only be done using the REST end point 

/admin/inventory_levels/set.json

am I missing something?

Take care,

Roy.

rplum Member
Posts:
6
5 months ago

Ryan,

It appears that the REST api is not working for updating inventory levels.

GET requests are working fine, but POST requests like 

/admin/inventory_levels/adjust.json

or 

/admin/inventory_levels/set.json

return an html response instead of a json response.

I also tried PUT which is how the varient endpoint work to make changes, in case the docs are wrong, but that got me a 406 unacceptable response.

This leaves me kind of dead in the water.

take care

Roy.

 

Ryan O Shopify Employee
Posts:
233
5 months ago

We are a private app, and we are getting the aforementioned error now when trying to create products, so what you have said regarding existing behavior is not true at least for this particular new client's store.  It woudl appear that we are closed off from selling to new clients until I can get this working.

New private apps will not be able to use the old behaviours.

 I would also like to say that it appears there is no way to directly set an inventory level to a specfic qty using GQL.   Tt appears that this can only be done using the REST end point 

If I recall correctly in GraphQL inventory level only has an adjust mutation, not a set.  So I don't think you are missing anything here.  You could do the math on your end.

GET requests are working fine, but POST requests like 

/admin/inventory_levels/adjust.json or /admin/inventory_levels/set.json

return an html response instead of a json response.

Can you show an example?  Make sure you aren't sending any cookies.  If the HTML response is a login page its due to the cookies.

rplum Member
Posts:
6
5 months ago

Ryan

I am using REST client for testing capi calls.  this has alwaysw worked in the past, so I dont know why it woudl stop for this.   PLease see screen shot.

Take care,

Roy.

Restclientpos to shopifyrest inventory level api thumb
Posts:
3
5 months ago

Hello Ryan, 

During post tracking API call for fulfilment , I am getting following error. 

"{"error":"location_id must be specified when creating fulfillments."}"

I believe this should not occure before august 1st?

Can you please help?

Thank you 

Peter Hurtadi Member
Posts:
6
5 months ago

hello I have a question, when you send my location_id in my request, your api answers the following error:

response: 
{"errors":"Not Found"}

request:

{"fulfillment":{"location_id":516876140657,"tracking_number":"794613732806","tracking_company":"FEDEX","tracking_url":"http:\/\/www.fedex.com\/Tracking?tracknumbers=794613732806","line_items":[{"id":1356647596145,"quantity":1}]}}

josehg Member
Posts:
1
5 months ago

Hi Ryan!

When doing a  POST /admin/inventory_levels/set.json to any other location than the one marked as "Shipping origin" we're getting the errror 403 "Shop does not have multi-location enabled". How to enable that, I can't find any setting for it. We're can we enable that?

Thank you!

Mendy Member
Posts:
3
Last edited 5 months ago

Hey @Ryan 

I'm posting the following:

body: { "fulfillment": { "location_id": 14041710634, "tracking_number": 23e24234234, "tracking_company": "UPS", "line_items": [{"id":1105987600426,"quantity":1},{"id":1105987633194,"quantity":1},{"id":1105987665962,"quantity":0}] }

ANd getting

HTTP error: #<RestClient::UnprocessableEntity: 422 Unprocessable Entity>

Each line in the order is set to be fulfilled through the Fulfillment Service specific with the Location_id I provided. 

Second question: if Fulfillment Service is set to Manual, can I fulfill from another location_id by simply passing through the new location_id?

Please help; 

Here's more information if this helps.

  • There are many items in the order
  • There are at least two fulfillment services (though they will all be filled by the same service), some are Manual. 
  • I'm not filling the entire order in one shot. I'm trying to fulfill only the items that have been fulfilled. 

 

Ben Member
Posts:
33
5 months ago

Hey Mendy,

I get the 422 error when an item or line item has already been fulfilled. Maybe check that?

Ben

Mendy Member
Posts:
3
5 months ago

Thanks, @Ben. None have been fulfilled. 

Here's more information if this helps.

  • There are many items in the order
  • There are at least two fulfillment services (though they will all be filled by the same service), some are Manual. 
  • I'm not filling the entire order in one shot. I'm trying to fulfill only the items that have been fulfilled. 

So I'm not sure what I'm doing wrong?

  1. Do the items all need to be associated to one service?
  2. Do the items need to be associated to this specific service before they are fulfilled
  3. So the Inventory_Item_id has to be associated to this location while I'm creating the fulfillment? 
  4. Presumably, then, I need to add a location to each line item - and not to the whole order (even though the whole order is being filled from the same location/service)?
Posts:
15
5 months ago

Guys, I have tried to unsubscribe to the million posts (and concerns) on this forum thread, but the unsubscribe link doesn't work. I'm also not subscribed to this thread via email yet still receive all the new post notifications. When I click on the unsubscribe link it tells me I'm not subscribed in a bottom red banner yet I still receive them CONSTANTLY. Can you fix the unsubscribe bug please ASAP. 

Posts:
40
5 months ago

We've put this into production, and it seems to be working for SOME of our stores and not for others. We did fill out the Google form and submit last week...)

FAIL:

{"inventory_level":{"inventory_item_id":12132895817801,"location_id":31747921,"available":1,"updated_at":"2018-07-26T11:23:43+10:00","admin_graphql_api_id":"gid:\/\/shopify\/InventoryLevel\/3052817?inventory_item_id=12132895817801"}}
HTTP/1.1 403 Forbidden

{"errors":"[API] This action requires merchant approval for write_inventory scope."}

 

Works for some:

{"inventory_level":{"inventory_item_id":12270741323860,"location_id":32207689,"available":2,"updated_at":"2018-07-25T18:22:03-07:00","admin_graphql_api_id":"gid:\/\/shopify\/InventoryLevel\/23783369?inventory_item_id=12270741323860"}}
HTTP/1.1 200 OK

 

 

 

 

Posts:
40
5 months ago

We solved our issue, stores had multiple locations. Trying the 2nd location solved this. Shout out to Ryan for his help!

Mendy Member
Posts:
3
4 months ago

So. Update. 

  1. You insert location on the fulfillment, not on the line items
  2. If there are different fulfillment services, you need to POST separately. 
  3. That said, once you POST, and you determine that one of the items are not the same fulfillment service (fails), you've now inserted a Fulfillment and it'll fail. You will need to POST to the other item separately (as you cannot post a single fulfillment for multiple services (locations)).

Here's what happened to us: We have two services, one manual, and another 'ACME logistics', the product was created outside of the 3PL app, so the service was only set to ACME AFTER the order was created. In this case, while there were two fulfillment services, Shopify treated them as THREE (as per Shopify support) - creating havoc. 

I hope @Adam Robson's unsubscribe issue is addressed. Nice weekend, 

Peter Hurtadi Member
Posts:
6
4 months ago

Hi, @Ryan 

 

 

since yesterday, the items of each order are not returning the locationId in any of my orders Do you know anything about this?

Ryan O Shopify Employee
Posts:
233
4 months ago

Hey Peter, would need some more info then that, there weren't any changes made.

 

Ryan

Peter Hurtadi Member
Posts:
6
Last edited 4 months ago

 

For example, these answers are from the same store (modify some data) but in an order  return the origin_location to which each item belongs and in the other not Why does this happen ? If each item is assigned to a location

 

Response 1

 

{
    "order": {
        "id": 122121212121211221,
        "email": "skaadlkad@gmail.com",
        "closed_at": null,
        "created_at": "2018-07-30T15:22:19-05:00",
        "updated_at": "2018-07-30T15:22:27-05:00",
        "number": 22890,
        "note": null,
        "token": "skaadlkad3233232",
        "gateway": "pago_directo_con_tarjeta_de_crédito_y_débito_powered_by_paypal_",
        "test": false,
        "total_price": "1208.10",
        "subtotal_price": "1079.10",
        "total_weight": 2000,
        "total_tax": "0.00",
        "taxes_included": true,
        "currency": "ARN",
        "financial_status": "paid",
        "confirmed": true,
        "total_discounts": "119.90",
        "total_line_items_price": "1199.00",
        "cart_token": null,
        "buyer_accepts_marketing": false,
        "name": "CH23890",
        "referring_site": "https://www.google.com.AR/",
        "landing_site": "/",
        "cancelled_at": null,
        "cancel_reason": null,
        "total_price_usd": "64.87",
        "checkout_token": "skaadlkad3233232lksakldadal",
        "reference": null,
        "user_id": null,
        "location_id": null,
        "source_identifier": null,
        "source_url": null,
        "processed_at": "2018-07-30T15:22:19-05:00",
        "device_id": null,
        "phone": null,
        "customer_locale": "es",
        "app_id": 580111,
        "browser_ip": null,
        "landing_site_ref": null,
        "order_number": 23890,
        "discount_applications": [
            {
                "type": "discount_code",
                "value": "10.0",
                "value_type": "percentage",
                "allocation_method": "across",
                "target_selection": "all",
                "target_type": "line_item",
                "code": "#SoyChamp"
            }
        ],
        "discount_codes": [
            {
                "code": "#sadad",
                "amount": "119.90",
                "type": "percentage"
            }
        ],
        "note_attributes": [],
        "payment_gateway_names": [
            "pago_directo_con_tarjeta_de_crédito_y_débito_powered_by_paypal_"
        ],
        "processing_method": "offsite",
        "checkout_id": 2323232323232,
        "source_name": "web",
        "fulfillment_status": null,
        "tax_lines": [],
        "tags": "",
        "contact_email": "skaadlkad@gmail.com",
        "order_status_url": "https://Asdaasadadasdad.comSldadljadad",
        "admin_graphql_api_id": "gid://shopify/Order/122121212121211221",
        "line_items": [
            {
                "id": 1372597944431,
                "variant_id": 17423517190,
                "title": "Hydadskasdklalda",
                "quantity": 1,
                "price": "499.00",
                "sku": "HCDTSB003",
                "variant_title": "",
                "vendor": "Hydracup",
                "fulfillment_service": "manual",
                "product_id": 5588403782,
                "requires_shipping": true,
                "taxable": true,
                "gift_card": false,
                "name": "Hydadskasdklalda",
                "variant_inventory_management": "shopify",
                "properties": [],
                "product_exists": true,
                "fulfillable_quantity": 1,
                "grams": 0,
                "total_discount": "0.00",
                "fulfillment_status": null,
                "discount_allocations": [
                    {
                        "amount": "49.90",
                        "discount_application_index": 0
                    }
                ],
                "admin_graphql_api_id": "gid://shopify/LineItem/1372597944431",
                "tax_lines": [],
                "origin_location": {
                    "id": 106020044812,
                    "country_code": "AR",
                    "province_code": "QRO",
                    "name": "scsakas.AR",
                    "address1": "assalksalkdas",
                    "address2": "sakldad",
                    "city": "dsklak",
                    "zip": "11223"
                }
            },
            {
                "id": 211222121,
                "variant_id": 12305832411247,
                "title": "Maleta Pkjasdjaadjajads",
                "quantity": 1,
                "price": "700.00",
                "sku": "074892 01",
                "variant_title": "",
                "vendor": "scsakas.AR",
                "fulfillment_service": "manual",
                "product_id": 1345506082927,
                "requires_shipping": true,
                "taxable": true,
                "gift_card": false,
                "name": "Maleta Pkjasdjaadjajads",
                "variant_inventory_management": "shopify",
                "properties": [],
                "product_exists": true,
                "fulfillable_quantity": 1,
                "grams": 2000,
                "total_discount": "0.00",
                "fulfillment_status": null,
                "discount_allocations": [
                    {
                        "amount": "70.00",
                        "discount_application_index": 0
                    }
                ],
                "admin_graphql_api_id": "gid://shopify/LineItem/211222121",
                "tax_lines": [],
                "origin_location": {
                    "id": 106020044812,
                    "country_code": "AR",
                    "province_code": "QRO",
                    "name": "scsakas.AR",
                    "address1": "assalksalkdas",
                    "address2": "sakldad",
                    "city": "dsklak",
                    "zip": "11223"
                }
            }
        ],
        "shipping_lines": [
            {
                "id": 470162866287,
                "title": "Envío Nacional Básico (3 a 7 dias hábiles) *Tiempo & Costo adicional en zonas extendidas*",
                "price": "129.00",
                "code": "Envío Nacional Básico (3 a 7 dias hábiles) *Tiempo & Costo adicional en zonas extendidas*",
                "source": "shopify",
                "phone": null,
                "requested_fulfillment_service_id": null,
                "delivery_category": null,
                "carrier_identifier": null,
                "discounted_price": "129.00",
                "discount_allocations": [],
                "tax_lines": []
            }
        ],
        "billing_address": {
            "first_name": "alfero",
            "address1": "sadksadjadldakjd",
            "phone": "21122212",
            "city": "Treew",
            "zip": "22114",
            "province": "Nuevo Leon",
            "country": "Mexico",
            "last_name": "adame",
            "address2": "Blanco y Cuellar",
            "company": "casa",
            "latitude": 20.23323232,
            "longitude": -103.23322332,
            "name": "alfero adame",
            "country_code": "AR",
            "province_code": "JAL"
        },
        "shipping_address": {
            "first_name": "alfero",
            "address1": "sadksadjadldakjd",
            "phone": "21122212",
            "city": "Treew",
            "zip": "22114",
            "province": "Nuevo Leon",
            "country": "Mexico",
            "last_name": "adame",
            "address2": "Blanco y Cuellar",
            "company": "casa",
            "latitude": 20.23323232,
            "longitude": -103.23322332,
            "name": "alfero adame",
            "country_code": "AR",
            "province_code": "JAL"
        },
        "fulfillments": [],
        "client_details": {
            "browser_ip": "112212122112",
            "accept_language": "es-ES,es;q=0.9",
            "user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
            "session_hash": "871ab8c331d6347953381541197ad4d2",
            "browser_width": 1343,
            "browser_height": 662
        },
        "refunds": [],
        "customer": {
            "id": 676089233519,
            "email": "skaadlkad@gmail.com",
            "accepts_marketing": false,
            "created_at": "2018-07-27T12:58:57-05:00",
            "updated_at": "2018-08-06T12:37:41-05:00",
            "first_name": "alfero",
            "last_name": "adame",
            "orders_count": 1,
            "state": "enabled",
            "total_spent": "1208.10",
            "last_order_id": 122121212121211221,
            "note": null,
            "verified_email": true,
            "multipass_identifier": null,
            "tax_exempt": false,
            "phone": null,
            "tags": "socialshopwave, ssw-gplus",
            "last_order_name": "CH23890",
            "admin_graphql_api_id": "gid://shopify/Customer/676089233519",
            "default_address": {
                "id": 735594512495,
                "customer_id": 676089233519,
                "first_name": "alfero",
                "last_name": "adame",
                "company": "casa",
                "address1": "sadksadjadldakjd",
                "address2": "Blanco y Cuellar",
                "city": "Treew",
                "province": "Nuevo Leon",
                "country": "Mexico",
                "zip": "22114",
                "phone": "21122212",
                "name": "alfero adame",
                "province_code": "JAL",
                "country_code": "AR",
                "country_name": "Mexico",
                "default": true
            }
        }
    }
}

Response 2

 

{
    "order": {
        "id": 577120698479,
        "email": "asdsad@gmail.com",
        "closed_at": null,
        "created_at": "2018-08-14T10:33:17-05:00",
        "updated_at": "2018-08-15T11:29:04-05:00",
        "number": 22987,
        "note": null,
        "token": "0e8a14e2f0904c86ac038ffbb0fb52d1",
        "gateway": "Deposito Bancario, Pago en Oxxo",
        "test": false,
        "total_price": "829.00",
        "subtotal_price": "730.00",
        "total_weight": 0,
        "total_tax": "0.00",
        "taxes_included": true,
        "currency": "MXN",
        "financial_status": "paid",
        "confirmed": true,
        "total_discounts": "0.00",
        "total_line_items_price": "730.00",
        "cart_token": "asdsa",
        "buyer_accepts_marketing": false,
        "name": "CH23987",
        "referring_site": "https://www.google.com.mx/",
        "landing_site": "/products/balon-voleibol-mikasa-competitive-class-verde",
        "cancelled_at": null,
        "cancel_reason": null,
        "total_price_usd": "43.29",
        "checkout_token": "asdsad",
        "reference": null,
        "user_id": null,
        "location_id": null,
        "source_identifier": null,
        "source_url": null,
        "processed_at": "2018-08-14T10:33:17-05:00",
        "device_id": null,
        "phone": null,
        "customer_locale": "es",
        "app_id": 580111,
        "browser_ip": null,
        "landing_site_ref": null,
        "order_number": asdasd,
        "discount_applications": [],
        "discount_codes": [],
        "note_attributes": [],
        "payment_gateway_names": [
            "Deposito Bancario, Pago en Oxxo"
        ],
        "processing_method": "manual",
        "checkout_id": asdada,
        "source_name": "web",
        "fulfillment_status": null,
        "tax_lines": [],
        "tags": "",
        "contact_email": "sadaddad@gmail.com",
        "order_status_url": "",
        "admin_graphql_api_id": "",
        "line_items": [
            {
                "id": 1403336622191,
                "variant_id": 19098822406,
                "title": "Producto 1",
                "quantity": 2,
                "price": "365.00",
                "sku": "BVMMVA002",
                "variant_title": "",
                "vendor": "Mikasa",
                "fulfillment_service": "manual",
                "product_id":233322332,
                "requires_shipping": true,
                "taxable": true,
                "gift_card": false,
                "name": "Balsadsad",
                "variant_inventory_management": null,
                "properties": [],
                "product_exists": true,
                "fulfillable_quantity": 2,
                "grams": 0,
                "total_discount": "0.00",
                "fulfillment_status": null,
                "discount_allocations": [],
                "admin_graphql_api_id": "gid://shopify/LineItem/asdsadaa",
                "tax_lines": []
            }
        ],
        "shipping_lines": [
            {
                "id": 481680326767,
                "title": "Envío Nacional Básico (3 a 7 dias hábiles) *Tiempo & Costo adicional en zonas extendidas*",
                "price": "99.00",
                "code": "Envío Nacional Básico (3 a 7 dias hábiles) *Tiempo & Costo adicional en zonas extendidas*",
                "source": "shopify",
                "phone": null,
                "requested_fulfillment_service_id": null,
                "delivery_category": null,
                "carrier_identifier": null,
                "discounted_price": "99.00",
                "discount_allocations": [],
                "tax_lines": []
            }
        ],
        "billing_address": {
            "first_name": "Jasdadd",
            "address1": "AVsadsadadadad",
            "phone": "33232323",
            "city": "asdsadad",
            "zip": "323232323",
            "province": "sadsada",
            "country": "Mexico",
            "last_name": "asdada",
            "address2": "sm asdadd",
            "company": "GRUdssadaddads S.A. DE C.V.",
            "latitude": 23322332,
            "longitude": 2332332,
            "name": "asdadsad",
            "country_code": "MX",
            "province_code": "Q ROO"
        },
        "shipping_address": {
            "first_name": "sdasddada LUIS ",
            "address1": "asdlsakda",
            "phone": "03323223232",
            "city": "dsadada",
            "zip": "23323232",
            "province": " Roo",
            "country": "Mexico",
            "last_name": "adas,dsamd",
            "address2": "sm 29",
            "company": "GRsdadadada.",
            "latitude": 21.2323232233,
            "longitude": -86.84332323232323672,
            "name": "Jlasdlsadlkaldka",
            "country_code": "MX",
            "province_code": "Q ROO"
        },
        "fulfillments": [],
        "client_details": {
            "browser_ip": "lksdaslñkada",
            "accept_language": "es-ES,es;q=0.9",
            "user_agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
            "session_hash": null,
            "browser_width": 1349,
            "browser_height": 662
        },
        "refunds": [],
        "customer": {
            "id": 32323232,
            "email": "lksadksadsad@gmail.com",
            "accepts_marketing": false,
            "created_at": "2018-01-08T15:41:50-06:00",
            "updated_at": "2018-08-15T11:29:04-05:00",
            "first_name": "JOSE dsdsadaLUIS",
            "last_name": "dasd",
            "orders_count": 2,
            "state": "invited",
            "total_spent": "829.00",
            "last_order_id": 577120698479,
            "note": null,
            "verified_email": true,
            "multipass_identifier": null,
            "tax_exempt": false,
            "phone": null,
            "tags": "",
            "last_order_name": "dasdada",
            "admin_graphql_api_id": "gid://shopify/Customer/3232323232",
            "default_address": {
                "id": 768512426095,
                "customer_id": 323232323,
                "first_name": "2332332 ",
                "last_name": "dsadad",
                "company": "GRUPO asddadsadad S.A. DE C.V.",
                "address1": "AV.casdsaada4",
                "address2": "sm 29",
                "city": "CANCUN",
                "province": "Quintana Roo",
                "country": "Mexico",
                "zip": "23323232",
                "phone": "01 9323322332",
                "name": "sadadadaO",
                "province_code": "Q ROO",
                "country_code": "MX",
                "country_name": "Mexico",
                "default": true
            }
        }
    }
}

 

Matt Member
Posts:
2
Last edited 3 months ago

Hey guys, I'm looking for a little insight here.

We create fulfillments for our clients' digital products. We're having trouble understanding how we can create a successful/completed fulfillment in one API call. Is this possible?

We have created our fulfillment service in each client's store, their products are now "stocked" at our fulfillment service location, but when we try to post a fulfillment we are always getting a pending fulfillment. Is this right? What is Shopify's recommended approach for fulfilling digital goods?

 

Edit: not sure if I'm supposed to tag anyone. @Ryan maybe you could help?

Posts:
59
3 months ago

Hi Matt,

You have to complete a fulfillment to show Fulfilled status.

Have a look here.

Matt Member
Posts:
2
3 months ago

Thanks @Bogdan,

We had tried the approach of marking a fulfillment as completed with success. We are still curious if this is the correct approach for digital goods. Our scenario is that one of our client's customers will purchase access to a digital course that we deliver. Once we receive an orders/paid webhook we electronically deliver access to the content to the purchaser and then attempt to create a fulfilled fulfillment.

We are wondering if there is any way to do this in one API call instead of two:
Posting a fulfilment with a completed status vs posting a fulfillment, reading the response's ID, and then posting a fulfillment completion.

Shouldn't we be able to do this for products that do not require shipping?

Ryan O Shopify Employee
Posts:
233
3 months ago

Hey Devs!

We've recently shipped a new change to help with identifying calls that we consider deprecated.  We've added a new header to return on these calls:

X-Shopify-API-Deprecated-Reason

If you receive one of these headers in your response, this means Shopify considers that a deprecated call.  This is an effort to allow these calls to be machine readable, and loggable, in order to assist developers in identifying the areas that need to be updated.

Examples of calls that will return this header:

  • Creating a fulfillment without a location
  • Creating a product with variants that have "inventory_quantity"
  • Creating a new variant on a product that has "inventory_quantity"
  • Updating a variant with "inventory_quantity_adjustment"
  • Updating a variant with "inventory_quantity"

 

Happy Coding!

Posts:
215
about 2 months ago

Hey Ryan,

I was wondering with the update of Locations on Private Apps, how can we remove the warning message which prevents storeowners from updating Locations feature? The Locations page shows a missing update on a Private Apps key from us saying the app is not supporting Locations. I updated the Private app endpoints to support Locations. How can I "re-run" the test to make the error message mark itself as solved? 

Thanks in adavnce for the help :D 

Cheers!

Entrepreneur, Developer, Geek, Gamer and very passionate about WEB development! :P Need help with your Shopify Store? Contact me: jfeuchter@gmail.com :D
Ryan O Shopify Employee
Posts:
233
about 2 months ago
g
1
upvotes

Hi Jurgen,

There is a daily automated to check to see if the app has made any deprecated calls within the past week.  Once there are no calls in the last week, the banner is removed.

Cheers,

Posts:
215
about 2 months ago

haha so I must wait a week :P Coolio haha thanks for the information. That should be added to the Locations Private Apps documentation. 

Cheers!

Entrepreneur, Developer, Geek, Gamer and very passionate about WEB development! :P Need help with your Shopify Store? Contact me: jfeuchter@gmail.com :D
Posts:
86
about 1 month ago

Hey Ryan,

We have one customer of our app who had recently switched to a multi-location inventory setup and their inventory items are currently connected to a "Custom fulfillment service" location.

Following the API docs, when we POST to `/inventory_levels/set.json`, we specify `disconnect_if_necessary:true` in the request.

However, only one of their inventory items was able to get a successful response and the rest are giving a 422 error with the message: "Could not deactivate item at its location"

Any ideas what could be causing this?

 

Ryan O Shopify Employee
Posts:
233
about 1 month ago

Hi Jonathan, generally that is because the item has open pending commitments (needs to be fulfilled on an order).  In order to force relocate these commitments to the new location you should use an /admin/inventory_levels/connect.json call with relocate_if_necessary: true.

 

 

Posts:
86
about 1 month ago

Hey Ryan,

Thanks for the explanation!

I was checking with the customer over the weekend and had him send me over a screenshot of the variant detail page and noticed a field called "Inventory managed by" and it was set to this 3rd Party Fuliifillment Service.

I asked him if it's possible for him to change that to "Shopify" but apparently they can't do that as it would affect their process.

So I just want to confirm: for them to be able to use Shopify's multi-location inventory feature, the "Inventory managed by" field has to be set to "Shopify" correct? And there's no other way around it?

Ryan O Shopify Employee
Posts:
233
about 1 month ago

So I just want to confirm: for them to be able to use Shopify's multi-location inventory feature, the "Inventory managed by" field has to be set to "Shopify" correct? And there's no other way around it?

It really depends on what you mean by this.  Having variants controlled by a fulfillment service just means that that variant is managed by the fulfillment service.  A variant can not be stocked at a fulfillment service ("legacy" location), and a standard location simultaneously. That is the only restriction on it, which is on a per variant level.

Posts:
86
about 1 month ago

Hey Ryan,

I think I understand.

So if they want to use Shopify's multi-location inventory feature, the "Inventory managed by" setting on the variant page will have to be set to "Shopify" right, since these are all Standard locations?

And if they change their mind later and want to go back to the Legacy location, they can change that setting back to that 3rd party fulfillment service but then they can't use the multi-location feature as you can't set the inventory on both the Legacy location and one of the Standard locations?

Ryan O Shopify Employee
Posts:
233
about 1 month ago

So if they want to use Shopify's multi-location inventory feature, the "Inventory managed by" setting on the variant page will have to be set to "Shopify"

I still don't know what you mean by this. What part of the feature?

An inventory item can be stocked at any amount of locations where legacy = false, but only one if legacy = true.  That is the restriction to inventory when using a fulfillment service to manage the item.  Setting an inventory item to managed by a fulfillment service, stocks that item at the location tied to that fulfillment service.

 

Hopefully that clears up the question?

Posts:
86
about 1 month ago

Hey Ryan,

Sorry for all these questions. 

The main thing I want to confirm is what the "Inventory managed by" setting should be for the merchant to be able to use multiple Standard locations. (for whatever reason, the UI also seems a little different in his store also, on our test store with multi-location enabled, it simply says "Fulfillment Service" instead of "Inventory managed by").

My assumption is this would need to be set to "Shopify" to be able to set inventory in the Standard locations, correct?

 

Posts:
86
about 1 month ago

Just realized I was basically going in circles.  What you said makes sense and I confirmed in the Shopify admin that you can only set inventory levels in multiple locations per variant if the "Inventory managed by" setting is set to "Shopify" (as the Location options disappear if you select something else).

Thanks and sorry again for all the comments!