Fulfillable location ID in Order API

The first place I was going to look other than the API was the webhook data sent for orders/create → https://shopify.dev/docs/admin-api/rest/reference/events/webhook. But that request body doesn’t indicate a fulfillment site at all. This really is odd. For those clients who are looking to act off this data. From everything I see, unless they directly hit the Shopify web admin they can’t get the info.

Hey everyone.

I’ve made significant progress on this. What is needed is to use the Fulfillment Orders endpoint. https://shopify.dev/docs/admin-api/rest/reference/shipping-and-fulfillment/fulfillmentorder and be use Merchant-managed fulfillment orders to enable.

as this will enable the Fulfillment Order endpoint to actually be populated with what is shown in the Shopify Admin.

Its not perfect, as it gives you the entire history of the all the order fulfillments that have been available in the past and there is not timestamp, but you can use the `

“status”: “in_progress” or "open"to see the current ones. If a split has been fulfilled, it will be marked asClosed`

More details. Used in the Fulfillment Orders endpoint will return an array of this format.

I’ve combined 2 different examples here so the screenshots may not match perfectly.

For partial fulfillments at a specific location will move the FulfillmentOrder to be In Progress ( Location B has 2 items. 1x test Item A, 2x test item B. If 1 of the 2 test item B were fulfilled, it would show In progress). If nothing has been fulfilled yet, they will appear as Open for status

If you look at my last post with the screen shots, you’ll see that I called this FulfillmentOrder endpoint using the GraphQL API and it still showed the incorrect location.

Hmmm let me take a look. I’ve successfully finished and delivered the feature I needed by using the Fulfillment order endpoint via REST.

@Gregarican You do not want a Fulfillment Service, I initially thought the same thing. This is a completely different feature in Shopify which caused confusions for me. If you update the app permissions to have Merchant-managed fulfillment orders permissions and then add assigned_location_id on the node where you call line_items, I believe this should work.

1 Like

Yes, I compared a REST API request to a GraphQL API request. Both for the same FulFillmentOrder endpoint. The assigned_location data in the REST API response contained the correct location that the line item was to be pulled from (per the Shopify web admin). Whereas the GraphQL API response contained the incorrect location. There isn’t an assigned_location property that I can see in the GraphQL API endpoint. Like I said I could likely be missing something, but based on my observations it appears as if the REST API works as expected for this, whereas the GraphQL API doesn’t provide.

.

Disregard, as I answered my own question in terms of GraphQL. Here is the query that worked. Duh!

{
  order(id: "gid://shopify/Order/2684801679522") {
    fulfillmentOrders(first: 10) {
      edges {
        node {
          assignedLocation {
            name
          }
          id
          lineItems(first: 10) {
            edges {
              node {
                lineItem {
                  id
                  name
                }
              }
            }
          }
        }
      }
    }
  }
}

I actually did get that far with fulfilment orders too, which does give you the assigned locations.

The other piece of the puzzle (in my case at least) is getting the quantities available at other locations, to work out if another location could be used. It only seems possible to get the unreserved quantity available.

@Mark_Stewart

Have you seen this endpoint. This will tell you all the locations that something can be moved too. https://shopify.dev/docs/admin-api/rest/reference/shipping-and-fulfillment/locationsformove

I haven’t used it yet but looks promising.

I think you can do it all in one shot, in terms of a single GraphQL API request. Here’s an example, where I can pull an order to see it’s assignedLocation, as well as the inventoryLevels where else it’s currently available. Although this still doesn’t resolve the “reserved” quantities that by default might have been linked to other orders. Therefore perhaps a second query would be required.

{
  order(id: "gid://shopify/Order/2684801679522") {
    name
    fulfillmentOrders(first: 5) {
      edges {
        node {
          id
          lineItems(first: 5) {
            edges {
              node {
                lineItem {
                  id
                  name
                  variant {
                    inventoryItem {
                      inventoryLevels(first: 5) {
                        edges {
                          node {
                            available                            
                            location {
                              name
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          assignedLocation {
            name
          }
        }
      }
    }
  }
}

Although if you also pull the deactivationAlert and canDeactivate fields in the single GraphQL API request it does inform you that a 0 available item is committed to an unfulfilled order. See below.

{
  order(id: "gid://shopify/Order/2684801679522") {
    name
    fulfillmentOrders(first: 5) {
      edges {
        node {
          id
          lineItems(first: 5) {
            edges {
              node {
                lineItem {
                  id
                  name
                  variant {
                    inventoryItem {
                      inventoryLevels(first: 5) {
                        edges {
                          node {
                            available   
                            deactivationAlert
                            canDeactivate
                            location {
                              name
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          assignedLocation {
            name
          }
        }
      }
    }
  }
}
{
  "data": {
    "order": {
      "name": "#1320",
      "fulfillmentOrders": {
        "edges": [
          {
            "node": {
              "id": "gid://shopify/FulfillmentOrder/2420702347426",
              "lineItems": {
                "edges": [
                  {
                    "node": {
                      "lineItem": {
                        "id": "gid://shopify/LineItem/5814392357026",
                        "name": "STSLVR DAVID YURMAN PERIDOT AND DIAMOND CABLE CUFF",
                        "variant": {
                          "inventoryItem": {
                            "inventoryLevels": {
                              "edges": [
                                {
                                  "node": {
                                    "available": 0,
                                    "deactivationAlert": "Can’t unstock from this location because it has unfulfilled orders.",
                                    "canDeactivate": false,
                                    "location": {
                                      "name": "Sawmill"
                                    }
                                  }
                                },
                                {
                                  "node": {
                                    "available": 0,
                                    "deactivationAlert": "Can’t unstock from this location because it has unfulfilled orders.",
                                    "canDeactivate": false,
                                    "location": {
                                      "name": "Easton"
                                    }
                                  }
                                },
                                {
                                  "node": {
                                    "available": 1,
                                    "deactivationAlert": "1 unit of inventory at this location will be deleted.",
                                    "canDeactivate": true,
                                    "location": {
                                      "name": "Green Hills"
                                    }
                                  }
                                },
                                {
                                  "node": {
                                    "available": 0,
                                    "deactivationAlert": null,
                                    "canDeactivate": true,
                                    "location": {
                                      "name": "Weber"
                                    }
                                  }
                                }
                              ]
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "assignedLocation": {
                "name": "Easton"
              }
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 423,
      "actualQueryCost": 21,
      "throttleStatus": {
        "maximumAvailable": 1000,
        "currentlyAvailable": 979,
        "restoreRate": 50
      }
    }
  }
}

This is a good thread, I’ve seen this requested quite often (and a few times by me haha) to get the location ID that shows up in the order page, via the REST API + GraphQL so everyone wins.

It would be REALLY COOL if Shopify would just put a property in the line item of the Order data that says assigned_location_id (and maybe assigned_location_name too if you want to be double cool)… so that you could see the location from the API like you do on the order details page.

This would solve the issue and make a bunch of developers happy. :smiley: :+1:

6 Likes

Thanks @Gregarican , your GraphQL solution works. Because the order webhook object doesn’t contain location_id, I am immediately hitting GraphQL to grab this field once the webhook comes in. The maddening thing I just realized is, the node comes up empty when doing this in real-time - probably because the order doesn’t yet exist?? Either way, I have to throw a sleep() to create some buffer and make sure the order data exists by the time I query GraphQL.

Like others have mentioned, it would be great if the location_id just showed up in the order webhook object itself without requiring a separate query with a clumsy built-in delay.