Creating & updating inventory product offerings via the Etsy API in Python

Managing products and product variations in the Etsy API can be a bit tricky, especially when you want to “sync” them, i.e. either create or update in the Etsy API according to your own product data.

Here’s an approach in Python that I got working.

Say your product data looks like this:


my_products = {
    "sku_123": {"style": "foo", "price": "15.00", "quantity": 30},
    "sku_456": {"style": "bar", "price": "25.00", "quantity": 10},
}

One approach is to fetch the existing Etsy listing’s “inventory” (which might be empty for a newly created one), update it to match your local data, and then put it back to the Etsy API.

You can create new Etsy product offerings with this basic template structure:


new_etsy_product_offering = {
    "sku": "sku_123",
    "property_values": [
        {
            "property_id": 123,
            "property_name": "Style",
            "values": ["super cool style"],
        }
    ],
    "offerings": [
        {
            "price": "15.00",
            "quantity": 10,
            "is_enabled": 1,
            "is_deleted": 0,
        }
    ],
    "is_deleted": 0,
}

To update an existing Etsy product offering, you’ll need to get the JSON for it from Etsy and match it to the corresponding SKU in your local data (see below), before updating the relevant fields, which might look something like this:


etsy_product = {
    # JSON from Etsy for one product item in the inventory response
}
etsy_product["sku"] = "sku_123"
etsy_product["property_values"][0]["values"] = ["super cool style"]
etsy_product["offerings"][0]["price"] = "15.00"
etsy_product["offerings"][0]["quantity"] = 10

Your exact requirements might be a bit different, especially if your product data has a more complex structure than just variations in one property.

Reduced to its bare essentials, the overall approach looks something like this:


from requests_oauthlib import OAuth1Session

etsy_api = OAuth1Session(
    "{etsy client key}",
    client_secret="{etsy client secret}",
    resource_owner_key="{etsy resource owner key}",
    resource_owner_secret="{etsy resource owner secret}",
)

my_products = {
    "sku_123": {"style": "foo", "price": "15.00", "quantity": 30},
    "sku_456": {"style": "bar", "price": "25.00", "quantity": 10},
}

listing_id = 123456789
property_id = 123
get_inventory = etsy_api.get(f"/listings/{listing_id}/inventory")
inventory = get_inventory.json()["results"]

rebuilt_etsy_products = []

for sku, my_product in my_products.items():
    matched = None
    for etsy_product in inventory["products"]:
        if etsy_product["sku"] == sku:
            matched = product
            break
        if etsy_product["property_values"][0]["values"][0] == my_product["style"]
            matched = product
            break
    if not matched:
        matched = {
            "sku": sku,
            "property_values": [
                {
                    "property_id": property_id,
                    "property_name": "Style",
                    "values": [my_product["style"]],
                }
            ],
            "offerings": [
                {
                    "price": my_product["price"],
                    "quantity": my_product["quantity"],
                    "is_enabled": 1,
                    "is_deleted": 0,
                }
            ],
            "is_deleted": 0,
        }
    matched["sku"] = sku
    matched["property_values"][0]["values"] = [my_product["style"]]
    matched["offerings"][0]["price"] = my_product["price"]
    matched["offerings"][0]["quantity"] = my_product["quantity"]
    rebuilt_etsy_products.append(matched)

inventory["products"] = rebuilt_etsy_products

etsy_api.put(
    f"/listings/{listing_id}/inventory",
    {
        "listing_id": listing_id,
        "products": json.dumps(inventory["products"]),
        "price_on_property": [property_id],
        "quantity_on_property": [],
        "sku_on_property": [property_id],
    },
)

This approach is working quite well to manage the Etsy inventory for different print materials and sizes in Moment Wall Art.


Tech mentioned