Products¶
Products are the core of your e-commerce store. The Konigle SDK provides comprehensive support for creating and managing products with or without variants, including rich content, SEO metadata, and inventory management.
Creating a Product Without Variants¶
For simple products that don't have variations like size or color, you can create a basic product:
from decimal import Decimal
from konigle import Client
from konigle.models.commerce.product import ProductCreate, ProductStatus
from konigle.models import SEOMeta
# Initialize the client
client = Client(api_key="your_api_key")
# Create a simple product
product_data = ProductCreate(
title="Premium T-Shirt",
handle="premium-t-shirt",
status=ProductStatus.DRAFT,
product_type="Clothing",
vendor="Fashion Co",
tags="cotton,comfortable,premium",
price=Decimal("29.99"),
currency="USD",
content={
"time": 1672531200000,
"blocks": [
{
"type": "paragraph",
"data": {"text": "Premium quality cotton t-shirt."},
}
],
"version": "2.28.0",
},
seo_meta=SEOMeta(
description="Premium cotton t-shirt for everyday wear",
keywords="t-shirt, cotton, premium, clothing",
og_title="Premium T-Shirt",
og_description="High-quality cotton t-shirt",
),
)
# Create the product
product = client.products.create(product_data)
print(f"Created product: {product.title}")
print(f"Product ID: {product.uid}")
print(f"Handle: {product.handle}")
print(f"Has variants: {product.has_variants}")
Creating a Product With Variants¶
When your product comes in multiple options (like size and color), you can create variants during product creation:
from decimal import Decimal
from konigle import Client
from konigle.models.commerce.product import ProductCreate, ProductOption, ProductStatus
from konigle.models.commerce.product_variant import ProductVariantCreate
from konigle.models import SEOMeta
# Initialize the client
client = Client(api_key="your_api_key")
# Define product options
options = [
ProductOption(name="Size", values=["S", "M", "L", "XL"]),
ProductOption(name="Color", values=["White", "Black", "Navy"]),
]
# Create variants that match the options
variants = [
ProductVariantCreate(
price=Decimal("29.99"),
option1="M",
option2="Red",
sku="SHIRT-M-RED",
inventory_quantity=50,
),
ProductVariantCreate(
price=Decimal("31.99"),
option1="L",
option2="Blue",
sku="SHIRT-L-BLUE",
inventory_quantity=30,
),
]
# Create product with variants
product_data = ProductCreate(
title="Premium T-Shirt",
handle="premium-t-shirt",
status=ProductStatus.DRAFT,
product_type="Clothing",
vendor="Fashion Co",
tags="cotton,comfortable,premium",
currency="USD",
content={
"time": 1672531200000,
"blocks": [
{
"type": "paragraph",
"data": {"text": "Premium quality cotton t-shirt."},
}
],
"version": "2.28.0",
},
seo_meta=SEOMeta(
description="Premium cotton t-shirt for everyday wear",
keywords="t-shirt, cotton, premium, clothing",
og_title="Premium T-Shirt",
og_description="High-quality cotton t-shirt",
),
options=options,
variants=variants,
)
# Create the product
product = client.products.create(product_data)
print(f"Created product: {product.title}")
print(f"Product ID: {product.uid}")
print(f"Has variants: {product.has_variants}")
print(f"Number of options: {len(product.options)}")
# Variant titles are auto-generated from options
for variant in product_data.variants:
print(f"Variant: {variant.title} - SKU: {variant.sku}")
Updating a Product¶
You can product attributes using partial updates:
from konigle import Client
from konigle.models.commerce.product import ProductUpdate, ProductStatus
# Initialize the client
client = Client(api_key="your_api_key")
# Update product fields
update_data = ProductUpdate(
title="Updated Premium T-Shirt",
status=ProductStatus.ACTIVE,
tags="cotton,comfortable,premium,updated",
)
# Update the product
product_id = "c6ce805b-6dfb-4f66-91fb-797f9f5e60fa"
updated_product = client.products.update(product_id, update_data)
print(f"Updated product: {updated_product.title}")
print(f"Status: {updated_product.status}")
print(f"New price: {updated_product.price}")
Adding New Variants During Product Update¶
You can add new variants to an existing product by updating the product with new variant data:
from decimal import Decimal
from konigle import Client
from konigle.models.commerce.product import ProductUpdate
from konigle.models.commerce.product_variant import ProductVariantUpdate
# Initialize the client
client = Client(api_key="your_api_key")
# Create new variant updates
new_variants = [
ProductVariantUpdate(
price=Decimal("25.99"),
sku="SHIRT-XS-YELLOW",
inventory_quantity=25,
option1="XS",
option2="Yellow",
),
ProductVariantUpdate(
price=Decimal("35.99"),
sku="SHIRT-XXL-GREEN",
inventory_quantity=15,
option1="XXL",
option2="Green",
),
]
# Update product with new variants
update_data = ProductUpdate(
title="Updated Premium T-Shirt",
variants=new_variants,
)
# Update the product
product_id = "c6ce805b-6dfb-4f66-91fb-797f9f5e60fa"
updated_product = client.products.update(product_id, update_data)
print(f"Updated product: {updated_product.title}")
print(f"Has variants: {updated_product.has_variants}")
The new variants will be appended to the existing list of variants or replace them based on option matching.
Product Status Management¶
Products have different status levels for publication workflow:
from konigle.models.commerce.product import ProductStatus, ProductUpdate
# Available statuses
print(ProductStatus.DRAFT) # "draft"
print(ProductStatus.ACTIVE) # "active"
print(ProductStatus.ARCHIVED) # "archived"
# Update product status
update_data = ProductUpdate(status=ProductStatus.ACTIVE)
updated_product = client.products.update(product_id, update_data)
print(f"Product status: {updated_product.status}")
print(f"Published at: {updated_product.published_at}")
Listing Products¶
Basic Product Listing¶
# List all products with pagination
products = client.products.list(page=1, page_size=20)
print(f"Total products: {products.count}")
print(f"Current page: {products.current_page}")
print(f"Total pages: {products.num_pages}")
for product in products.payload:
print(f"- {product.title} ({product.status})")
print(f" Handle: {product.handle}")
print(f" Price: {product.price} {product.currency}")
print(f" Has variants: {product.has_variants}")
# Check if there are more pages
if products.has_next():
next_page = client.products.list(page=2, page_size=20)
Filtering Products¶
from konigle.filters.commerce import ProductFilters
# Using filter object (type-safe)
product_filters = ProductFilters(
q="t-shirt", # Search in title, handle, and tags
status="active", # Only active products
product_type="Clothing",
vendor="Fashion Co",
ordering="-created_at" # Newest first
)
filtered_products = client.products.list(
page=1,
page_size=10,
filters=product_filters
)
# Using filter kwargs (more concise)
active_products = client.products.list(
status="active",
q="premium",
ordering="title" # Sort by title
)
# Filter by product type
clothing_products = client.products.list(product_type="Clothing")
# Filter by vendor
vendor_products = client.products.list(vendor="Fashion Co")
# Search by text query
search_results = client.products.list(q="cotton t-shirt")
# Get draft products for review
draft_products = client.products.list(
status="draft",
ordering="-updated_at"
)
Getting a Specific Product¶
# Get product by ID
product = client.products.get("prod_123456789")
print(f"Product: {product.title}")
print(f"Status: {product.status}")
print(f"Price: {product.price} {product.currency}")
print(f"Vendor: {product.vendor}")
print(f"Product type: {product.product_type}")
print(f"Tags: {product.tags}")
# Check if product has variants
if product.has_variants:
print(f"Number of options: {len(product.options)}")
for option in product.options:
print(f" {option.name}: {', '.join(option.values)}")
# Access SEO metadata
if product.seo_meta:
print(f"SEO Title: {product.seo_meta.title}")
print(f"Description: {product.seo_meta.description}")
Iterating All Products¶
# Memory-efficient iteration over all products
for product in client.products.iter_all(page_size=50):
print(f"Processing product: {product.title}")
# Process each product...
# With filtering - get all active products
for product in client.products.iter_all(page_size=50, status="active"):
print(f"Processing active product: {product.title}")
# Get products by vendor
for product in client.products.iter_all(vendor="Fashion Co"):
print(f"Processing {product.vendor} product: {product.title}")
Working with Product Options¶
Product options define the dimensions for variants (size, color, etc.):
from konigle.models.commerce.product import ProductOption, ProductUpdate
# Define comprehensive options
options = [
ProductOption(
name="Size",
values=["XS", "S", "M", "L", "XL", "XXL"]
),
ProductOption(
name="Color",
values=["White", "Black", "Navy", "Red", "Green"]
),
ProductOption(
name="Material",
values=["Cotton", "Polyester", "Blend"]
),
]
# Update product options
update_data = ProductUpdate(options=options)
updated_product = client.products.update(product_id, update_data)
print(f"Number of options: {len(updated_product.options)}")
for option in updated_product.options:
print(f"{option.name}: {', '.join(option.values)}")
Deleting a Product¶
When you delete a product, all associated data is permanently removed. This includes:
- Product variants: All variants of the product are deleted
- Product images: All images associated with the product are deleted
- Product metadata: SEO data, content, and other associated information
!!! warning "Cascading Delete" Deleting a product is irreversible and will permanently remove all variants, images, and associated data. Make sure you have backups if needed.
from konigle import Client
# Initialize the client
client = Client(api_key="your_api_key")
# Delete a product by ID
product_id = "c6ce805b-6dfb-4f66-91fb-797f9f5e60fa"
try:
client.products.delete(product_id)
print(f"Product {product_id} has been successfully deleted")
print("All variants and images have been removed as well")
except Exception as e:
print(f"Failed to delete product: {e}")
Soft Delete Alternative¶
Instead of permanently deleting a product, consider archiving it:
from konigle.models.commerce.product import ProductUpdate, ProductStatus
# Archive the product instead of deleting
update_data = ProductUpdate(status=ProductStatus.ARCHIVED)
archived_product = client.products.update(product_id, update_data)
print(f"Product archived: {archived_product.status}")
print("Product data is preserved and can be reactivated later")
Error Handling¶
The SDK includes validation for common mistakes:
from decimal import Decimal
from konigle.models.commerce.product import ProductCreate
from konigle.models.commerce.product_variant import ProductVariantCreate
# Price validation
try:
# This will raise a ValueError
invalid_product = ProductCreate(
title="Test Product",
price=Decimal("-10.00"), # Negative price not allowed
)
except ValueError as e:
print(f"Price validation error: {e}")
try:
# This will also raise a ValueError
invalid_variant = ProductVariantCreate(
price=Decimal("0.00"), # Zero price not allowed
)
except ValueError as e:
print(f"Variant price validation error: {e}")
# Inventory validation
try:
# This will raise a ValueError
invalid_variant = ProductVariantCreate(
price=Decimal("29.99"),
inventory_quantity=-1, # Negative inventory not allowed
)
except ValueError as e:
print(f"Inventory validation error: {e}")
Async Support¶
All product operations support async/await:
import asyncio
from konigle import AsyncClient
from konigle.models.commerce.product import ProductCreate
async def create_product_async():
async_client = AsyncClient(api_key="your_api_key")
product_data = ProductCreate(
title="Async Product",
handle="async-product",
)
product = await async_client.products.create(product_data)
print(f"Created async product: {product.title}")
await async_client.close()
# Run the async function
asyncio.run(create_product_async())