A Day in the Life of a Shopify Order

TomShopify1 Comment

This post is part of a series following my building of the Best Sellers app to help Shopify stores manage and promote best selling products. If you'd like to start at the beginning of the series, you can start here.

This week’s post is all about what goes on behind-the-scenes when changes are made over the lifetime of a Shopify Order.

The Shopify Order docs give a great overview of the types of operations that can be performed on a Shopify Order. However, for my upcoming Best Sellers Shopify app, I also need to understand how each of these changes impact the order data. This will allow me to accurately track best-sellers while excluding things like refunded or canceled items.

In this post, I’ll cover:

  • A process for testing how Shopify handles different changes to an order.
  • Creating a test order within Shopify.
  • Detailed examples of how Shopify handles some of the most common types of order changes.

The Process

The process for testing how Shopify handles different changes to an order is fairly straight-forward:

  1. Use the Shopify Draft Order interface to create a test order.
  2. Make changes to the Order using Shopify’s Admin interface.
  3. Get the current Shopify Order JSON from the Shopify Order API after each change to see what changed.

In an effort to cover the most common set of changes to an order, I moved a test order through the following set of changes:

Shopify Order Timeline

The Test Order

Here is the test order I will reference throughout the rest of this post:

Shopify Create Draft Order

The test order contains three line items to give a good sampling of the different types of line items we may find in a Shopify Order:

  • The Ectoplasm is a Custom Item, which means it is not tied to an actual Shopify product.

    Custom Items can be created manually and applied to an order within the Shopify Admin:

    Shopify Create Custom Item


  • The Ghostbusters Movie is a Product that does not have any options.
  • The Stay Puft Costume is an item that has an option for Gender. In this case, the Gender selected is Mens.

Order Created

After I created the test order, I called the Shopify Order API to fetch the JSON data for the initial order. Here is initial order JSON data:

Here are some highlights of the newly created order:

  • The financial_status is set to pending.
  • The fulfillment_status is not set.
  • The Ghostbuster Movie line_item has a variant_id even though there are no options. This is because Shopify actually creates a single variant behind the scenes for products without options.
  • The Ectoplasm line_item:
    • has no value set for product_id, variant_id, sku or vendor. This means any tracking of these types of line items must use another mechanism.
    • has product_exists set to false. This may prove useful in helping support Custom Item handling.

Payment Received

To see what happens to an order when payment is received, I marked the order as paid in the Shopify Admin. Here is a condensed version of the order JSON after marking the order as paid:

This resulted in the following changes to the order:

  • The fulfillment_status was set to fulfilled.
  • The customer[“total_spent”] was set to the full transaction amount of 71.98.

NOTE: For the remainder of this post, the JSON samples will all be condensed to only highlight the changes that occurred from the most recent changes.

Partial Fulfillment

Now let’s pretend we are able to ship Ectoplasm and Ghostbusters Movie items, but the Stay Puft Costume is not ready yet. To do this, I created a fulfillment in the Shopify Admin. Here are the changes after the fulfillment was created:

Here’s a summary of the changes after a partial fulfillment:

  • The fulfillment_status for the order changed to partial.
  • For each of the fulfilled line items:
    • The fulfillable_quantity changed from 1 to 0.
    • The fulfillment_status changed from not set to fulfilled.
  • There is a new entry in the fulfillments array to represent this change. This includes the line_items that were fulfilled, as well as shipping information such as tracking numbers.

Fulfillment Complete

Next up I wanted to see what happens when all items are fulfilled in an order. Using the same technique as the last step, I marked the Stay Puft Costume as fulfilled. This resulted in the following order changes:

Here are some of the highlights after all items in an order are fulfilled:

  • The order fulfillment_status changed from partial to fulfilled.
  • The fulfillable_quantity changed from 1 to 0 for the Stay Puft Costume.
  • The fulfillment_status changed from not set to fulfilled for the Stay Puft Costume.
  • A new entry was add to the fulfillments section.

Partial Refund

The next scenario I wanted to test is how Shopify handles refunds for items in an order. I decided to test this first as a partial refund, and later we’ll perform a full refund. I created a partial refund for the Stay Puft Costume line item.

Here are the changes to the order after a partial refund:

Here are the highlights of the partial refund of an order:

  • The financial_status of the order changed from paid to partially_refunded.
  • An entry was added to the refunds section with full details of the line_item that was refunded.
  • The original line_item for refunded items remains unchanged. To get an accurate view of the state of each line_item, both the line_items section and refunds sections must be used.
  • The customer[“total_spent”] was reduced by the amount of the refund to 29.98.

Order Archived

Next let’s try archiving the order and see what happens. Here are the changes to the order JSON after archiving the order:

The only thing that changed is the closed_at property was set to the date and time of the change. As you can see from the naming of the field, archive is the same as close in Shopify. This difference in terminology was initially confusing to me. The Order API docs use the term close instead of archive.

Order Unarchived

Now let’s see what happens when we unarchive an order. Here are the changes to the order JSON after unarchiving the order:

Nothing surprising here – the closed_at is no longer set.

Full Refund

Now let’s pretend the customer changed their mind and wants a full refund. Here are the changes to the order JSON after refunding the remaining items on this order:

Here are the highlights after a the full refund of an order:

  • The financial_status of the order changed from partially_refunded to refunded.
  • An entry was added to the refunds section with details of the additional line_items that were refunded. NOTE: I am only showing the new refund entry in the above JSON for the sake of brevity.
  • The customer[“total_spent”] was reduced by the amount of the refund to 0.00.

Order Canceled

Since all of the items have been refunded, I went ahead and canceled the order as a final step. Here are the changes to the order JSON after we cancel the order:

Canceled orders have only two properties that change:

  • The cancelled_at is set to the date and time of the cancellation.
  • The cancel_reason is set to the reason that is selected during the cancellation.

Signup to be notified about future Shopify App development articles

Get Shopify App development tips and tricks straight to your inbox.


This concludes our tour through the different stages of the life of a Shopify Order.

Sometimes to get a thorough understanding of a complex platform like Shopify, the best way to do so is through a series of controlled changes and then observing the result.

By using this same technique, it should be possible to get a deep understanding of what goes on behind-the-scenes of Shopify for any other process not covered in this post.

One Comment on “A Day in the Life of a Shopify Order”

  1. Pingback: Working With Shopify Data Using Postgres JSONB - Burst Commerce

Leave a Reply

Your email address will not be published. Required fields are marked *