Managing Inventory and Product Variants with the Etsy API (with Python Examples)

Nicole Dow
4 min readNov 21, 2020
Photo by Denny Müller on Unsplash

Wading through API documentation can sometimes leave you with more questions than answers when it comes to making actual API calls. In this post, I hope to offer some concrete, practical examples of interacting with Etsy’s inventory endpoints. The examples will be written in Python, as Etsy’s documentation is mostly focused on PHP examples and I wish to provide other developers with a wider range of examples. I believe Python can be more easily translated to any other programming language that readers may be familiar with.

All examples will be written without any specific Etsy API Python library, although there are a few out there. There are a few reasons why:

  • At the time of writing, I could only find Etsy API Python packages that were written more than 3 years ago, and hadn’t been updated. Since it is difficult to find currently maintained packages, I’d rather rely on my own code. Maybe someday I’ll find the time to make my own package!
  • I want my examples to be clear and more transferable to other programming languages.

Authenticate Yourself with OAuth So You Can Manage Inventory

I will save a deep dive into how to get an OAuth token for Etsy for another post, but this Etsy Documentation is a good place to start.

You will need to save an OAuth1 session object to a variable. For this you will need your app’s API key, your app’s API secret, and the shop’s OAuth token and token secret for this app.

from requests_oauthlib import OAuth1Sessiondef create_etsy_session(self):
session = OAuth1Session(API_KEY, API_SECRET, self.token,
self.token_secret)
return session

Create an Etsy Listing

If you already have an etsy listing, you just need the listing_id, which can be found in your listing’s URL, right after /listing .

Otherwise, create an Etsy listing via a simple POST request to https://openapi.etsy.com/v2/listings, with a simple Python dictionary converted to JSON as the request body. The example below will include some comments explaining what certain fields signify. For more information, visit the Etsy listing documentation here.

*Please note all request URLs for the Etsy API will begin with https://openapi.etsy.com/v2/

import requests
import json
etsy = self.create_etsy_session()listing_data = {
'quantity': 999, # a maximum of 1000 is allowed
'title': 'Merry Christmas Ornament',
'description': 'A beautiful hand-painted ornament',
'price': 14.99,
'shipping_template_id': 1234,
'taxonomy_id': int(self.etsy_taxonomy_id),
'state': 'draft',
'who_made': 'i_did',
'is_supply': False,
'when_made': 'made_to_order',
'write_missing_inventory': True,
'item_height': 3,
'item_length': 3,
'item_width': 3,
'item_dimensions_unit': 'in',
'item_weight_unit': 'oz',
'item_weight': 2
}
request_url = 'https://openapi.etsy.com/v2/listings'
etsy.post(request_url, listing_data)

A few notes on listing pushes in Etsy:

  • A default shipping template ID is required. This is how Etsy will know what shipping information to display in your listing. If you don’t have a shipping template, create one via a POSTrequest to /shipping/templates , as described here in the createShippingTemplate method.
  • The keys who_made, is_supply, and when_made are required by Etsy and only accept certain string values, which you can find here under the respective fields.

Updating the Inventory and Setting Variant Data

Etsy once supported “Variations”, i.e. specific combinations of product attributes such as Size and Color. Now, the concept of a variant is tied to the ListingInventoryand ListingOffering endpoints.

The ListingInventory endpoint returns an array of products (among other information), which represent these combinations of attributes, with information on how many of each combination are in stock.

At this time, you cannot update the inventory for just one specific product. You must completely replace the inventory with all your products and their quantity data each time the inventory is updated.

How you determine your variants will depend on your database structure and your application. You will need to serialize all your product attributes and inventory quantities into a dictionary that looks like this:

inventory = [
{
'sku': 'product1sku',
'property_values': [
{
'property_id': 100,
'property_name': 'Size',
'values': ['Medium']
},
{
'property_id': 100,
'property_name': 'Color',
'values': ['Pink']
}
],
'offerings': [
{'price': variant_price, 'quantity': 10}
]
}
]

A few notes on the above code:

  • The example inventory array has only one inventory item — a medium pink shirt. You will need an object like this one for each combination of size and color.
  • The property_ids are not random — they are predefined by Etsy. If you know the taxonomy classification you want to sell your product in, you can find the available property ids via a call to GET /taxonomy/seller/:taxonomy_id/properties . See here for more information.

Now, we will add this array, as JSON, to the ‘products’ key in the rest of our request body. We will then set up an OAuth client (a little differently this time, as Etsy gets picky with PUT requests).

Our final request will look like this:

from requests_oauthlib import oauth1
import json
import requests
inventory_request_data = {
'listing_id': 1234567,
'products': json.dumps(inventory),
'price_on_property': #here, add the property_id of any attribute that determines price
}
client = oauth1.Client(API_KEY, API_SECRET, token, token_secret, signature_method=SIGNATURE_PLAINTEXT)req_url = 'https://openapi.etsy.com/v2/listings/%s/inventory'%(listing_id)uri, headers, body = client.sign(req_url)headers['Content-Type'] = 'application/x-www-form-urlencoded'r = requests.session()
r.put(uri, headers=headers, data=inventory_request_data)

One thing to watch out for here is that if you add a property to the “price_on_property” key, you must keep your pricing consistent for all variants with a specific property value attached to this property. For example, if you say the price depends on size, all of your “small” shirts must align in price and all your “medium” shirts must align in price, and so on and so forth.

And voilà ! Your Etsy inventory is updated.

--

--