Solved

Python ShopifyAPI unable to save orders fulfillments

albe89albe
Tourist
4 1 4

Hello, I am using the ShopifyAPI python library in its version 12.3.0 (the latest at this time).

 

My code has been working perfectly for two weeks (with daily execution). But since last week, the same code without any changes become unable to fulfill orders. This is the function I use:

 

 

 

 

    def fulfillOrder(self, order, tracking_number) -> bool:

        fulfillment = shopify.Fulfillment({
            'order_id': order.id,
            'line_items': [line_item for line_item in order.line_items if line_item.fulfillment_status != 'fulfilled'],
            'location_id': self.location
        })
        fulfillment.tracking_number = tracking_number
        fulfillment.notify_customer = True
        response = fulfillment.save()
        return response

 

 

 

 

 

The error I am getting is in the fulfillment.save() line, and the error is:

 

 

 

 

Exception has occurred: ResourceNotFound
Not Found: https://MY_STORE.myshopify.com/admin/orders/ORDER_ID/fulfillments.json
urllib.error.HTTPError: HTTP Error 404: Not Found

During handling of the above exception, another exception occurred:

  File "C:\path\of\my\project\ShopifyConnector.py", line 104, in fulfillOrder
    response = fulfillment.save()
               ^^^^^^^^^^^^^^^^^^
  File "C:\path\of\my\project\TrackingBot.py", line 75, in <module>
    success = sc.fulfillOrder(order, tracking)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pyactiveresource.connection.ResourceNotFound: Not Found: https://MY_STORE.myshopify.com/admin/orders/ORDER_ID/fulfillments.json

 

 

 

 

(I have redacted MY_STORE and ORDER_ID, but the are both valid)

 

However, if I enter in that URL that is suposedly returning a 404 in a web browser, I get a valid JSON response:

 

 

 

 

{"fulfillments":[]}

 

 

 

 

 

Also, other jobs of my code are working properly, like getting all the unfulfilled orders from the last N days. So it is not an athentication issue. Moreover, the right permissions are granted, so it is not an authorization issue.

 

This is happening not with one specific order, but with all of them.

 

Does anyone have any idea on how to address this issue?

Thanks in advance

Accepted Solution (1)

albe89albe
Tourist
4 1 4

This is an accepted solution.

Well, after making some research and receiving confirmation by @Liam. It was clear that my issue is due to a recent endpoints deprecation in the Shopify API.

 

Since I couldn't wait for the ShopifyAPI Python library to be updated, I reimplemented my fulfillOrder() method for not to use the library and perform the requests to API directly.

 

If you are facing a similar issue and when you are reading this and the library is still not updated... here you have my code to serve as inspiration 😅.

 

 

def fulfillOrder(self, order, tracking_number) -> object:

        # First get the FulfillmentOrder to create the Fulfillment in it
        # https://shopify.dev/docs/api/admin-rest/2023-07/resources/fulfillmentorder#get-orders-order-id-fulfillment-orders
        endpoint = 'https://' + self.SHOP_NAME + '.myshopify.com/admin/api/' + self.API_VERSION + '/orders/' + str(order.id) + '/fulfillment_orders.json'
        response = requests.get(endpoint, headers={'X-Shopify-Access-Token':str(self.API_TOKEN)})
        fulfillment_orders = response.json()['fulfillment_orders']

        # Find all the 'open' FulfillmentOrders to work with them and fulfill the entire order
        fulfillment_order_items = []
        for fulfillment_order in fulfillment_orders:
            if fulfillment_order['status'] == 'open' and fulfillment_order['delivery_method']['method_type'] == 'shipping':
                fulfillment_order_items.append( {'fulfillment_order_id': fulfillment_order['id']} )

        if len(fulfillment_order_items) == 0:
            return None

        # Create the Fulfillment data to save
        # https://shopify.dev/docs/api/admin-rest/2023-07/resources/fulfillment#post-fulfillments
        data = {
            'fulfillment': {
                'line_items_by_fulfillment_order': fulfillment_order_items,
                'tracking_info': {
                    'number': tracking_number
                },
                'notify_customer': True
            }
        }

        # Save the Fulfillment
        endpoint = 'https://' + self.SHOP_NAME + '.myshopify.com/admin/api/' + self.API_VERSION + '/fulfillments.json'
        response = requests.post(endpoint, json=data, headers={'X-Shopify-Access-Token':str(self.API_TOKEN), 'Content-Type': 'application/json'})

        return response

 

Note that my specific project requirements could not match with yours, as this method fulfills all the pending shippable items in the order.

 

Important documentation articles consulted to code this method:

 

In order to be able to use the endpoints, your app needs to have these permissions granted:

  • write_assigned_fulfillment_orders
  • read_assigned_fulfillment_orders
  • write_merchant_managed_fulfillment_orders
  • read_merchant_managed_fulfillment_orders
  • write_third_party_fulfillment_orders
  • read_third_party_fulfillment_orders

 

Hope this is helpful for someone, hope the python library is updated soon and hope Shopify take some years to deprecate this endpoints 😂

 

Happy coding!

View solution in original post

Replies 6 (6)

Liam
Shopify Staff
2731 301 778

Hi Albe89albe,

 

Is it possible that your app is using some endpoints that have been deprecated recently - which could be causing this 404 if the requested resource is no longer available?

 

There were recent deprecations on some endpoint deprecations on the Fulfillment API - can you confirm you're not making calls to any of these endpoints?

Liam | Developer Advocate @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

albe89albe
Tourist
4 1 4

Hi Liam, thanks for your response.

 

Indeed, the issue is due to the deprecated endpoints. The major problem here is that, as can be seen in my former code, I wasn't making any request directly, but just using the ShopifyAPI Python library, which is still pointing to the deprecated endpoints.

 

I supposed that, since the library author is Shopify, every update to the API will be synchronized with an update to the library... but it seems that there is some delay on that.

 

I couldn't wait for a library update and I've already solve this problem by not using the library and making the requests directly to the endpoints explained in the 2023-07 API documentation.

 

I will now share my solution because I think that everyone using the library is having this same issue right now.

albe89albe
Tourist
4 1 4

This is an accepted solution.

Well, after making some research and receiving confirmation by @Liam. It was clear that my issue is due to a recent endpoints deprecation in the Shopify API.

 

Since I couldn't wait for the ShopifyAPI Python library to be updated, I reimplemented my fulfillOrder() method for not to use the library and perform the requests to API directly.

 

If you are facing a similar issue and when you are reading this and the library is still not updated... here you have my code to serve as inspiration 😅.

 

 

def fulfillOrder(self, order, tracking_number) -> object:

        # First get the FulfillmentOrder to create the Fulfillment in it
        # https://shopify.dev/docs/api/admin-rest/2023-07/resources/fulfillmentorder#get-orders-order-id-fulfillment-orders
        endpoint = 'https://' + self.SHOP_NAME + '.myshopify.com/admin/api/' + self.API_VERSION + '/orders/' + str(order.id) + '/fulfillment_orders.json'
        response = requests.get(endpoint, headers={'X-Shopify-Access-Token':str(self.API_TOKEN)})
        fulfillment_orders = response.json()['fulfillment_orders']

        # Find all the 'open' FulfillmentOrders to work with them and fulfill the entire order
        fulfillment_order_items = []
        for fulfillment_order in fulfillment_orders:
            if fulfillment_order['status'] == 'open' and fulfillment_order['delivery_method']['method_type'] == 'shipping':
                fulfillment_order_items.append( {'fulfillment_order_id': fulfillment_order['id']} )

        if len(fulfillment_order_items) == 0:
            return None

        # Create the Fulfillment data to save
        # https://shopify.dev/docs/api/admin-rest/2023-07/resources/fulfillment#post-fulfillments
        data = {
            'fulfillment': {
                'line_items_by_fulfillment_order': fulfillment_order_items,
                'tracking_info': {
                    'number': tracking_number
                },
                'notify_customer': True
            }
        }

        # Save the Fulfillment
        endpoint = 'https://' + self.SHOP_NAME + '.myshopify.com/admin/api/' + self.API_VERSION + '/fulfillments.json'
        response = requests.post(endpoint, json=data, headers={'X-Shopify-Access-Token':str(self.API_TOKEN), 'Content-Type': 'application/json'})

        return response

 

Note that my specific project requirements could not match with yours, as this method fulfills all the pending shippable items in the order.

 

Important documentation articles consulted to code this method:

 

In order to be able to use the endpoints, your app needs to have these permissions granted:

  • write_assigned_fulfillment_orders
  • read_assigned_fulfillment_orders
  • write_merchant_managed_fulfillment_orders
  • read_merchant_managed_fulfillment_orders
  • write_third_party_fulfillment_orders
  • read_third_party_fulfillment_orders

 

Hope this is helpful for someone, hope the python library is updated soon and hope Shopify take some years to deprecate this endpoints 😂

 

Happy coding!

Vinh
Shopify Partner
13 0 4

Hi @albe89albe really appreciate you posting your solution. I have the same problem and I will use your function until the shopify library is updated.

Cheers, 

Vinh

I build processes and products around Shopify and ReCharge API
jagdish_0106
Shopify Partner
4 0 0

Hello

 

who to grant this permission

 

  • write_assigned_fulfillment_orders
  • read_assigned_fulfillment_orders
  • write_merchant_managed_fulfillment_orders
  • read_merchant_managed_fulfillment_orders
  • write_third_party_fulfillment_orders
  • read_third_party_fulfillment_order
  •  
albe89albe
Tourist
4 1 4

Hello @jagdish_0106 

You should grant those permissions to the app that will perform the fulfillments.

 

Maybe "permissions" is not the best choice of word here, because I think it is actually called "API access scopes".

Here you have the reference: https://shopify.dev/docs/api/usage/access-scopes