Looking up a Shopify order by its name

One of the most common questions I get with ShopifySharp, my .NET library for working with the Shopify API, is "how do I find an order by its name"? If you look at the object representing a Shopify order, you'll find that they have two different "identifiers":

  1. An id property, e.g. 987654321, which doesn't really appear anywhere outside of the API, but is used by apps to identify specific orders.
  2. A name property, e.g. #1001, which is what merchants see everywhere -- they hardly see the ID property at all, if ever.

Since this order "name" is the thing that merchants see and know, you'd think that the Shopify API would have some kind of method for looking up an order by the name. But that doesn't seem to be the case. Honestly I'm not sure how Shopify envisions apps would implement any kind of search or lookup feature based on that order name -- maybe they want you to archive the entire list of the merchant's orders in your own database and perform the search yourself (although I can't imagine that's something their lawyers would be happy to hear, in the age of GDPR).

On the other hand, maybe they do support searching for orders by their name, and have simply forgotten to mention it literally anywhere. That seems to be closer to the truth, as a determined Google user will eventually surface an answer on StackOverflow that reveals an undocumentered parameter for the API call that lists orders; just pass a ?name=1001 in the querystring when listing orders and Shopify should respond with a list of orders that have a matching name property (in practice, it's probably only one single order since the name is unique).

As of February 7th, 2019, this call still works. You can easily test it for yourself from your terminal:

curl --header "X-Shopify-Access-Token: access_token" "https://mydomain.myshopify.com/admin/orders.json?name=1001"

But the problem isn't necessarily that you need to do some Googling to find out this is possible; the problem is that it is completely undocumented by Shopify. It is mentioned precisely zero times in their documentation, and therefore it most likely isn't officially supported by them and may break at any time.

That's a problem for people using ShopifySharp, though; because getting an order by its name is undocumented and presumably unsupported, I've resisted adding support for it to the package. Since these things can change at any time with no warning, I can only support things that are supported by Shopify itself. If I were to support undocumented things, Shopify could remove them whenever they see fit, and then one day I find myself swamped in issues and emails from developers who were using that feature and whose app has suddenly broken with its removal.

For example, see this issue on GitHub when Shopify changed their login mechanism for store owners, and by extension broke the AuthorizationService.IsValidShopDomainAsync() function. The function was making a request to domain.myshopify.com/admin and looking for an X-ShopId header, which was present on all Shopify shops at that URL. When they introduced their new login mechanism, calls to that specific URL would be redirected to a completely different domain -- a domain that had no X-ShopId header.

Extending ShopifySharp to search for orders by name

Reading the above is bound to sound disappointing if you're reading this trying to figure out how you can get an order by its name, but luckily there is a way that you can make this work with very little extra effort. I've had tons of requests for these undocumented things that people have found on StackOverflow, and while I don't support them, you can easily extend the package to make it do what you want.

Much of ShopifySharp has been designed with extensibility in mind, which was a byproduct of versions 1 and 2 having been designed more rigidly and then broken when Shopify made a change to their API with no announcement -- something they were very keen to do at the time. In particular, the services, models and filters have all been designed so that you can extend them and add your own custom properties or functions.

In ShopifySharp, most of the service.ListAsync() functions support an optional "filter" object, which translates its own properties to a querystring to filter the results down to those matching the properties that were given. So, for example, this filter:

var filter = new ListFilter
{
    Limit = 250
}

Sending this through a service.ListAsync(filter) call would internally be converted to the querystring ?limit=250. (Property and querystring keys are camelCased in Shopify but PascalCased in C# by convention.) When you're searching for an order by its name property, you need to make an HTTP request and pass name={name} in the querystring. ShopifySharp does not have an OrderFilter.Name property (because it's undocumented and unsupported), but since filters are simple C# classes, all you need to do is extend the filters with your own properties!

namespace ShopifySharp.Filters
{
    public class OrderFilterWithName : OrderFilter
    {
        /// <summary>
        /// The "name" of the order, e.g. #1001. Can be used to filter the results of a list operation to just those with the given name.
        /// </summary>
        [JsonProperty("name")]
        public string Name { get; set; }
    }
}

Once you've created this very simple extension, just pass it to the same service.ListAsync() method and ShopifySharp will automatically translate the Name property to the name in the request querystring, along with all the original properties on the extended OrderFilter class.

public async Task SearchForOrderAsync()
{
    var orderName = "1001";
    var filter = new OrderFilterWithName
    {
        Name = orderName,
        Limit = 1
    };
    var service = new OrderService(myShopifyDomain, accessToken);
    var orders = await service.ListAsync(filter);
}

Note that the # must be dropped. If you leave it in the querystring, Shopify will completely ignore the name parameter, so your search will not function as expected.

With that simple filter extension class, you're now able to look up orders by their name in your own Shopify app! This practice can also be applied to extending entire "services" in ShopifySharp. If you wanted to add a dedicated function to the OrderService that would look up an order by its name, all you need to do is extend the service like this:

namespace ShopifySharp
{
    public class OrderServiceWithNameLookup : OrderService
    {
        public OrderServiceWithNameLookup(string domain, string accessToken) : base(domain, accessToken)
        {

        }

        public async Task<Order> GetOrderByNameAsync(string orderName)
        {
            var filter = new OrderFilterWithName
            {
                Name = orderName.Replace("#", ""),
                Limit = 1
            };
            var orders = await this.ListAsync(filter);
    
            return orders.FirstOrDefault();
        }
    }
}

Using that same service extension pattern, you could even make the services return completely different types of objects! If you have any questions, or you need to hire someone to develop your Shopify app, contact me at joshua@nozzlegear.com.

Obligatory disclaimer: looking up an order by its name is undocumented and I do not support this (unless you want to pay me for that support). This article is just an example to help you accomplish your goals; keep in mind that these undocumented features may stop working at any time, and your application may break without warning.


Learn how to build rock solid Shopify apps with C# and ASP.NET!

Did you enjoy this article? I wrote a premium course for C# and ASP.NET developers, and it's all about building rock-solid Shopify apps from day one.

Enter your email here and I'll send you a free sample from The Shopify Development Handbook. It'll help you get started with integrating your users' Shopify stores and charging them with the Shopify billing API.

We won't send you spam. Unsubscribe at any time.