Creating and Managing Listings

Overview

Listings are the core of your Etsy shop. This chapter covers:

The Listing Object

A digital product listing includes:

{
    "listing_id": 1234567890,
    "title": "Monthly Planner Printable PDF",
    "description": "A beautiful monthly planner...",
    "price": {"amount": 499, "divisor": 100, "currency_code": "USD"},
    "quantity": 999,
    "tags": ["planner", "printable", "pdf", "monthly"],
    "state": "active",
    "is_digital": true,
    "file_data": "digital",
    "who_made": "i_did",
    "when_made": "2020_2025",
    "taxonomy_id": 2078,
    "views": 1250,
    "num_favorers": 45
}

Key fields for digital products:

Retrieving Listings

Get All Shop Listings

def get_all_listings(client, shop_id, state="active"):
    """Retrieve all listings with pagination."""
    listings = []
    offset = 0
    limit = 100  # Max per request
    
    while True:
        response = client.get(
            f"/application/shops/{shop_id}/listings",
            params={"state": state, "limit": limit, "offset": offset}
        )
        listings.extend(response["results"])
        if len(response["results"]) < limit:
            break
        offset += limit
    
    return listings

Get a Single Listing

listing = client.get(f"/application/listings/{listing_id}")

Filter Digital Listings

# Get only digital listings
listings = get_all_listings(client, shop_id)
digital_only = [l for l in listings if l.get("is_digital")]

Creating a New Listing

Required Fields

To create a digital listing, you need these minimum fields:

Field Description Example
title Product title (max 140 chars) “Budget Planner Printable”
description Full description “This printable planner…”
price Price in currency subunits 499 (= $4.99)
quantity Stock quantity 999
who_made Who made it “i_did”
when_made When made “2020_2025”
taxonomy_id Etsy category 2078
is_digital Digital flag true

Basic Listing Creation

def create_digital_listing(client, shop_id, title, description, price_cents, tags):
    data = {
        "title": title,
        "description": description,
        "price": price_cents,
        "quantity": 999,
        "who_made": "i_did",
        "when_made": "2020_2025",
        "is_digital": True,
        "taxonomy_id": 2078,  # Art & Collectibles > Prints > Digital
        "tags": tags[:13]  # Max 13 tags
    }
    return client.post(f"/application/shops/{shop_id}/listings", data=data)

Finding the Right Taxonomy ID

Etsy uses taxonomy IDs to categorize products. Find the right one:

# Get all taxonomies
taxonomies = client.get("/application/seller-taxonomy/nodes")

# Search for relevant categories
for tax in taxonomies["results"]:
    if "digital" in tax["name"].lower() or "print" in tax["name"].lower():
        print(f"{tax['id']}: {tax['name']}")

Common digital product taxonomies:

Updating Listings

Update Single Field

# Update just the price
client.put(
    f"/application/shops/{shop_id}/listings/{listing_id}",
    data={"price": 599}  # $5.99
)

Update Multiple Fields

updates = {
    "title": "Updated Title Here",
    "description": "New improved description...",
    "tags": ["new", "tags", "here"],
    "price": 699
}
client.put(f"/application/shops/{shop_id}/listings/{listing_id}", data=updates)

Bulk Operations

The real power of the API is bulk operations. See code/listings.py for complete implementations.

Update All Prices

def apply_sale_discount(client, shop_id, discount_percent):
    """Apply a percentage discount to all listings."""
    listings = get_all_listings(client, shop_id)
    
    for listing in listings:
        current_price = listing["price"]["amount"]
        new_price = int(current_price * (1 - discount_percent / 100))
        
        client.put(
            f"/application/shops/{shop_id}/listings/{listing['listing_id']}",
            data={"price": new_price}
        )
        print(f"Updated {listing['title']}: ${current_price/100} → ${new_price/100}")

Add Tags to Multiple Listings

def add_tags_to_listings(client, shop_id, listing_ids, new_tags):
    """Add tags to specific listings (max 13 tags total)."""
    for listing_id in listing_ids:
        listing = client.get(f"/application/listings/{listing_id}")
        current_tags = listing.get("tags", [])
        
        # Combine and limit to 13
        combined = list(set(current_tags + new_tags))[:13]
        
        client.put(
            f"/application/shops/{shop_id}/listings/{listing_id}",
            data={"tags": combined}
        )

Seasonal Tag Updates

def add_seasonal_tags(client, shop_id, season):
    """Add seasonal tags to relevant listings."""
    seasonal_tags = {
        "christmas": ["christmas", "holiday", "gift", "xmas"],
        "valentines": ["valentine", "love", "romantic", "february"],
        "backtoschool": ["school", "student", "teacher", "academic"]
    }
    
    tags = seasonal_tags.get(season, [])
    listings = get_all_listings(client, shop_id)
    
    for listing in listings:
        current_tags = listing.get("tags", [])
        updated = list(set(current_tags + tags))[:13]
        
        client.put(
            f"/application/shops/{shop_id}/listings/{listing['listing_id']}",
            data={"tags": updated}
        )

Listing States

Listings can have different states:

State Description
active Visible and purchasable
inactive Hidden from shop
draft Not yet published
expired Listing period ended
sold_out No inventory (rare for digital)

Deactivate a Listing

# Move to inactive
client.put(
    f"/application/shops/{shop_id}/listings/{listing_id}",
    data={"state": "inactive"}
)

Reactivate a Listing

# Make active again
client.put(
    f"/application/shops/{shop_id}/listings/{listing_id}",
    data={"state": "active"}
)

Deleting Listings

# Permanently delete (cannot be undone!)
client.delete(f"/application/shops/{shop_id}/listings/{listing_id}")

⚠️ Warning: Deletion is permanent. Consider deactivating instead.

Best Practices for Digital Listings

Title Optimization

def optimize_title(base_title, keywords):
    """Create SEO-optimized title (max 140 chars)."""
    parts = [base_title] + keywords
    title = " | ".join(parts)
    return title[:140]  # Truncate if too long

Description Template

DESCRIPTION_TEMPLATE = """
{main_description}

📁 WHAT'S INCLUDED:
{file_list}

📋 HOW TO USE:
1. Purchase and download
2. Open with {software}
3. Print at home or local print shop

💡 PLEASE NOTE:
- This is a DIGITAL download, no physical item shipped
- Colors may vary based on monitor and printer settings
- For personal use only

❓ QUESTIONS?
Message me anytime!
"""

Tag Strategy

def generate_tags(product_type, style, occasion=None):
    """Generate relevant tags for a listing."""
    tags = [product_type, f"{product_type} printable", f"digital {product_type}"]
    tags.extend([style, f"{style} {product_type}"])
    
    if occasion:
        tags.extend([occasion, f"{occasion} {product_type}"])
    
    # Always include these
    tags.extend(["instant download", "printable", "digital download"])
    
    return list(set(tags))[:13]  # Unique, max 13

Handling Rate Limits

When doing bulk operations, respect rate limits:

import time

def bulk_update_with_delay(client, shop_id, updates, delay=0.5):
    """Update multiple listings with delay between calls."""
    results = []
    for listing_id, data in updates.items():
        try:
            client.put(
                f"/application/shops/{shop_id}/listings/{listing_id}",
                data=data
            )
            results.append({"listing_id": listing_id, "status": "success"})
        except Exception as e:
            results.append({"listing_id": listing_id, "status": "error", "error": str(e)})
        
        time.sleep(delay)  # Prevent rate limiting
    
    return results

What’s Next

Creating a listing is just the first step. For digital products, you need to upload the actual files customers will download. That’s covered in the next chapter.


← Previous: Shop Management Next: Digital Files →

← Back to Table of Contents