Generated using AI. Be aware that everything might not be accurate.



Digital Files Management

Overview

The defining feature of digital products is the downloadable file. This chapter covers:

  • Uploading digital files to listings
  • Managing multiple files per listing
  • File requirements and limitations
  • Replacing and updating files

Digital File Basics

Each digital listing can have multiple downloadable files. When a customer purchases, they get access to download all files attached to that listing.

File Limitations

Constraint Limit
Max file size 20 MB per file
Max files per listing 5 files
Allowed formats Most common formats (PDF, PNG, JPG, ZIP, etc.)

For larger files, you’ll need to:

  • Compress files (ZIP)
  • Split into multiple listings
  • Use external delivery (link in digital file)

Uploading Files

Upload a Single File

def upload_digital_file(client, shop_id, listing_id, file_path, rank=1):
    """Upload a digital file to a listing."""
    with open(file_path, "rb") as f:
        response = client.post(
            f"/application/shops/{shop_id}/listings/{listing_id}/files",
            files={"file": f},
            data={"rank": rank, "name": file_path.name}
        )
    return response

The rank parameter determines download order (1 = first).

Upload Multiple Files

from pathlib import Path

def upload_all_files(client, shop_id, listing_id, file_paths):
    """Upload multiple files to a single listing."""
    results = []
    for rank, path in enumerate(file_paths, start=1):
        path = Path(path)
        if not path.exists():
            results.append({"file": str(path), "status": "not found"})
            continue
            
        try:
            result = upload_digital_file(client, shop_id, listing_id, path, rank)
            results.append({"file": path.name, "status": "uploaded"})
        except Exception as e:
            results.append({"file": path.name, "status": "error", "error": str(e)})
    
    return results

Listing Existing Files

def list_digital_files(client, shop_id, listing_id):
    """Get all digital files for a listing."""
    response = client.get(
        f"/application/shops/{shop_id}/listings/{listing_id}/files"
    )
    return response["results"]

Returns:

[
    {
        "listing_file_id": 123456,
        "listing_id": 1234567890,
        "rank": 1,
        "filename": "planner-2024.pdf",
        "filesize": "2.5 MB",
        "create_timestamp": 1699900000
    }
]

Deleting Files

def delete_digital_file(client, shop_id, listing_id, listing_file_id):
    """Remove a digital file from a listing."""
    client.delete(
        f"/application/shops/{shop_id}/listings/{listing_id}/files/{listing_file_id}"
    )

Replacing Files (Update Product)

When you update a product, you need to replace the file. Unfortunately, Etsy doesn’t have a direct “replace” endpoint—you must delete and re-upload:

def replace_digital_file(client, shop_id, listing_id, new_file_path):
    """Replace all files for a listing with a new file."""
    # 1. Get existing files
    existing = list_digital_files(client, shop_id, listing_id)
    
    # 2. Delete old files
    for file in existing:
        delete_digital_file(client, shop_id, listing_id, file["listing_file_id"])
    
    # 3. Upload new file
    return upload_digital_file(client, shop_id, listing_id, new_file_path)

⚠️ Important: Customers who already purchased retain access to the original files. New downloads get the updated files.

Practical Workflows

Batch File Upload for New Products

See code/digital_files.py for complete implementation.

def create_listing_with_files(client, shop_id, listing_data, file_paths):
    """Create a new listing and upload its files."""
    # 1. Create the listing
    listing = client.post(
        f"/application/shops/{shop_id}/listings",
        data=listing_data
    )
    listing_id = listing["listing_id"]
    
    # 2. Upload files
    for rank, path in enumerate(file_paths, 1):
        upload_digital_file(client, shop_id, listing_id, path, rank)
    
    return listing_id

Update Files Across Multiple Listings

If you have a common file (like a license or bonus) across listings:

def update_common_file_all_listings(client, shop_id, old_filename, new_file_path):
    """Replace a specific file across all listings that have it."""
    listings = get_all_listings(client, shop_id)
    updated = []
    
    for listing in listings:
        files = list_digital_files(client, shop_id, listing["listing_id"])
        
        for file in files:
            if file["filename"] == old_filename:
                # Delete old, upload new
                delete_digital_file(
                    client, shop_id, listing["listing_id"], file["listing_file_id"]
                )
                upload_digital_file(
                    client, shop_id, listing["listing_id"], new_file_path, file["rank"]
                )
                updated.append(listing["listing_id"])
    
    return updated

File Organization Best Practices

Naming Conventions

Use clear, consistent file names:

def format_filename(product_name, variant=None, extension="pdf"):
    """Create a clean, customer-friendly filename."""
    name = product_name.lower().replace(" ", "-")
    if variant:
        name = f"{name}-{variant}"
    return f"{name}.{extension}"

# Examples:
# monthly-planner.pdf
# monthly-planner-a4.pdf
# monthly-planner-letter.pdf

ZIP Files for Multiple Formats

When offering multiple formats, consider ZIPping them:

import zipfile
from pathlib import Path

def create_bundle_zip(files, output_name):
    """Create a ZIP bundle from multiple files."""
    zip_path = Path(output_name)
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        for file in files:
            zf.write(file, Path(file).name)
    return zip_path

README/Instructions File

Include a text file with instructions:

README_TEMPLATE = """
Thank you for your purchase!

FILES INCLUDED:
{file_list}

HOW TO PRINT:
1. Open the PDF file
2. Set print size to 100% (Actual Size)
3. Use high-quality paper for best results

NEED HELP?
Contact me through Etsy messages.

Terms: Personal use only. Do not redistribute.
"""

Handling Large Files

If your files exceed 20MB:

Option 1: Compression

import zipfile

def compress_file(input_path, output_path=None):
    """Compress a file using maximum ZIP compression."""
    input_path = Path(input_path)
    output_path = output_path or input_path.with_suffix('.zip')
    
    with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
        zf.write(input_path, input_path.name)
    
    return output_path, output_path.stat().st_size

Option 2: Split Files

For very large products, create multiple listings or use external delivery with a link file.

Verifying File Uploads

After uploading, verify files are attached:

def verify_listing_files(client, shop_id, listing_id, expected_count):
    """Verify the correct number of files are attached."""
    files = list_digital_files(client, shop_id, listing_id)
    actual_count = len(files)
    
    if actual_count != expected_count:
        return {
            "status": "mismatch",
            "expected": expected_count,
            "actual": actual_count,
            "files": [f["filename"] for f in files]
        }
    return {"status": "ok", "files": [f["filename"] for f in files]}

Common File Issues

“File too large”

  • Compress the file
  • Reduce image resolution
  • Split into multiple files

“Invalid file type”

  • Check allowed extensions
  • Rename with correct extension
  • Ensure file isn’t corrupted

“Upload failed”

  • Check network connection
  • Verify listing exists and is yours
  • Ensure authentication is valid

What’s Next

With listings created and files uploaded, the next chapter covers handling orders—what happens after customers purchase your digital products.


← Previous: Creating Listings Next: Orders & Fulfillment →

← Back to Table of Contents



>> You can subscribe to my mailing list here for a monthly update. <<