JK
JustKalm
v2.0.0Stable

Python SDK

Async-first Python SDK with full type hints, automatic retries, and built-in rate limiting. Designed for production workloads with enterprise-grade reliability.

Python 3.8+
Async/Await Support
Full Type Hints

Installation

PyPI Installationbash
pip install justkalm-sdk

Or install from source for the latest features:

pip install git+https://github.com/mybffjustin/justkalm-python.git

Python Version Requirement

The SDK requires Python 3.8 or higher. We recommend Python 3.10+ for best async performance.

Quick Start

quickstart.pypython
import asyncio
from justkalm import JustKalmClient, ProductCreateParams

async def main():
    # Initialize the client with your API key
    async with JustKalmClient(
        api_key="jk_live_your_api_key_here",
        environment="production"  # or "sandbox" for testing
    ) as client:
        
        # Create a product
        product = await client.products.create(ProductCreateParams(
            name="Organic Cotton T-Shirt",
            brand="EcoWear",
            category="apparel",
            materials={
                "organic_cotton": 0.95,
                "elastane": 0.05
            },
            certifications=["GOTS", "Fair Trade"]
        ))
        
        print(f"Created product: {product.id}")
        
        # Get valuation with health scoring
        valuation = await client.valuations.create(
            product_id=product.id,
            include_health=True,
            include_sustainability=True
        )
        
        print(f"Health Score: {valuation.health_score}/100")
        print(f"Sustainability Score: {valuation.sustainability_score}/100")
        print(f"Estimated Value: ${valuation.adjusted_value:.2f}")

if __name__ == "__main__":
    asyncio.run(main())

The SDK uses async context managers to ensure proper resource cleanup. Always use async with when creating clients.

Authentication

The SDK supports multiple authentication methods for flexibility in different environments.

# Set the environment variable
export JUSTKALM_API_KEY="jk_live_your_api_key_here"

# The SDK will automatically use it
from justkalm import JustKalmClient

async with JustKalmClient() as client:
    # API key is automatically loaded from env
    products = await client.products.list()

Products API

Create a Product

from justkalm import ProductCreateParams, MaterialComposition

product = await client.products.create(ProductCreateParams(
    name="Premium Leather Handbag",
    brand="LuxuryBrand",
    category="accessories",
    subcategory="handbags",
    materials=MaterialComposition(
        primary="full_grain_leather",
        breakdown={
            "full_grain_leather": 0.85,
            "brass": 0.10,
            "cotton_lining": 0.05
        }
    ),
    condition="excellent",
    original_price=1200.00,
    certifications=["Leather Working Group"],
    metadata={
        "color": "cognac",
        "year": 2023
    }
))

List Products

# List with pagination
products = await client.products.list(
    limit=50,
    offset=0,
    category="apparel",
    brand="EcoWear"
)

# Iterate through all products (auto-pagination)
async for product in client.products.iter():
    print(f"{product.name}: {product.health_score}/100")

Get and Update

# Get a specific product
product = await client.products.get("prod_abc123")

# Update a product
updated = await client.products.update(
    "prod_abc123",
    condition="good",
    metadata={"updated_at": "2024-01-15"}
)

# Delete a product
await client.products.delete("prod_abc123")

Valuations API

from justkalm import ValuationRequest

# Create a valuation
valuation = await client.valuations.create(
    product_id="prod_abc123",
    include_health=True,
    include_sustainability=True,
    include_market_analysis=True
)

# Access valuation results
print(f"Health Score: {valuation.health_score}/100")
print(f"Sustainability Score: {valuation.sustainability_score}/100")
print(f"Confidence: {valuation.confidence:.1%}")
print(f"Base Value: ${valuation.base_value:.2f}")
print(f"Adjusted Value: ${valuation.adjusted_value:.2f}")

# Access detailed breakdown
for factor in valuation.factors:
    print(f"  {factor.name}: {factor.impact:+.1%}")

# Get health details
health = valuation.health_details
print(f"Chemical Safety: {health.chemical_safety}/100")
print(f"Material Toxicity: {health.material_toxicity}/100")
for risk in health.identified_risks:
    print(f"  ⚠️ {risk.description}")

Error Handling

from justkalm.exceptions import (
    JustKalmError,
    AuthenticationError,
    RateLimitError,
    ValidationError,
    NotFoundError,
    ServerError
)

try:
    product = await client.products.get("prod_invalid")
except NotFoundError as e:
    print(f"Product not found: {e.message}")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
    # The SDK handles retries automatically by default
except ValidationError as e:
    print(f"Invalid request: {e.message}")
    for error in e.errors:
        print(f"  - {error.field}: {error.message}")
except AuthenticationError as e:
    print(f"Auth failed: {e.message}")
except ServerError as e:
    print(f"Server error (retryable): {e.message}")
except JustKalmError as e:
    # Catch-all for any SDK error
    print(f"Error: {e.message}")

Rate Limiting

The SDK includes built-in rate limiting to prevent 429 errors. You can customize the behavior:

from justkalm import JustKalmClient, RateLimitConfig

# Configure rate limiting
async with JustKalmClient(
    api_key="jk_live_...",
    rate_limit=RateLimitConfig(
        requests_per_second=10,
        requests_per_minute=500,
        burst_size=20,
        wait_on_limit=True  # Wait instead of raising error
    )
) as client:
    # SDK automatically respects limits
    for product_id in product_ids:
        await client.products.get(product_id)

# Check current rate limit status
status = client.rate_limit_status()
print(f"Remaining: {status.remaining}/{status.limit}")
print(f"Resets at: {status.reset_at}")

Retry Logic

from justkalm import JustKalmClient, RetryConfig

# Configure retry behavior
async with JustKalmClient(
    api_key="jk_live_...",
    retry=RetryConfig(
        max_retries=3,
        initial_delay=0.5,      # 500ms initial delay
        max_delay=30.0,         # Max 30s delay
        exponential_base=2.0,   # Double delay each retry
        jitter=True,            # Add random jitter
        retryable_errors=[      # Errors to retry
            "rate_limit",
            "server_error",
            "connection_error"
        ]
    )
) as client:
    # Retries happen automatically
    product = await client.products.get("prod_abc123")

Retry Timing

With default settings, the retry delays are: 500ms → 1s → 2s (with jitter). Total maximum wait time is ~4 seconds for 3 retries.

Batch Processing

from justkalm import BatchProcessor, ProductCreateParams

# Process large datasets efficiently
async with client.batch(
    concurrency=5,           # 5 concurrent requests
    chunk_size=100,          # Process 100 items at a time
    on_error="continue"      # Continue on individual failures
) as batch:
    
    products = [
        ProductCreateParams(
            name=f"Product {i}",
            brand="BatchBrand",
            category="apparel"
        )
        for i in range(1000)
    ]
    
    results = await batch.create_products(products)
    
    print(f"Created: {results.successful}")
    print(f"Failed: {results.failed}")
    
    for error in results.errors:
        print(f"  Error on item {error.index}: {error.message}")

# Or use the streaming batch processor
async for result in client.batch_stream(products):
    if result.success:
        print(f"Created: {result.product.id}")
    else:
        print(f"Failed: {result.error.message}")