Skip to main content

A modern, pythonic Katana Manufacturing ERP API client with automatic retries, rate limiting, and smart pagination

Project description

Katana Manufacturing ERP - Python API Client

A modern, pythonic Python client for the Katana Manufacturing ERP API. Built from a comprehensive OpenAPI 3.1.0 specification with 100% endpoint coverage and automatic resilience.

Python 3.11+ uv OpenAPI 3.1.0 CI codecov Docs Security

โœจ Features

  • ๐ŸŽฏ Production Ready: Automatic retries, rate limiting, and error handling
  • ๐Ÿš€ Zero Configuration: Works out of the box with environment variables
  • ๐Ÿ“ฆ Complete API Coverage: All 76+ Katana API endpoints with full type hints
  • ๐Ÿ”„ Smart Pagination: Automatic pagination with built-in safety limits
  • ๐Ÿ›ก๏ธ Transport-Layer Resilience: httpx-native approach, no decorators needed
  • โšก Async/Sync Support: Use with asyncio or traditional synchronous code
  • ๐Ÿ” Rich Observability: Built-in logging and metrics
  • ๐Ÿ—๏ธ Streamlined Architecture: Flattened imports, automated regeneration, zero patches

๐Ÿš€ Quick Start

Installation

# Clone the repository
git clone https://github.com/dougborg/katana-openapi-client.git
cd katana-openapi-client

# Install with uv (recommended)
uv sync --all-extras

# Or with pip
pip install -e .

๐Ÿ“‹ Configuration

The Katana client supports multiple authentication methods (in priority order):

  1. Direct parameter: Pass api_key to KatanaClient()
  2. Environment variable: Set KATANA_API_KEY
  3. .env file: Create a .env file with your credentials
  4. ~/.netrc file: Use standard Unix credential file

Option 1: .env file (Recommended)

Create a .env file with your Katana API credentials:

KATANA_API_KEY=your-api-key-here
# Optional: defaults to https://api.katanamrp.com/v1
KATANA_BASE_URL=https://api.katanamrp.com/v1

Option 2: ~/.netrc file

For centralized credential management, add to ~/.netrc:

machine api.katanamrp.com
password your-api-key-here

Note: Ensure your netrc file has restricted permissions (chmod 600 ~/.netrc)

Option 3: Environment variable

export KATANA_API_KEY=your-api-key-here

Option 4: Direct parameter

async with KatanaClient(api_key="your-api-key-here") as client:
    # ...

Basic Usage

KatanaClient (Recommended)

The modern, pythonic client with automatic resilience:

import asyncio

from katana_public_api_client import KatanaClient
from katana_public_api_client.api.product import get_all_products
from katana_public_api_client.api.sales_order import get_all_sales_orders

async def main():
    # Automatic configuration from .env file
    async with KatanaClient() as client:
        response = await get_all_products.asyncio_detailed(
            client=client,
            limit=50
        )
        print(f"Status: {response.status_code}")
        print(f"Products: {len(response.parsed.data)}")

        # Automatic pagination happens transparently
        all_products_response = await get_all_products.asyncio_detailed(
            client=client,
            is_sellable=True
        )
        print(f"Total sellable products: {len(all_products_response.parsed.data)}")

        # Direct API usage with automatic resilience
        orders_response = await get_all_sales_orders.asyncio_detailed(
            client=client,
            status="open"
        )
        orders = orders_response.parsed.data if orders_response.parsed else []
        print(f"Open orders: {len(orders)}")

asyncio.run(main())

See the Cookbook for more practical examples including inventory management, order processing, webhook handlers, and performance optimization.

๐Ÿ“Š API Coverage

The client provides access to all major Katana functionality:

Category Endpoints Description
Products & Inventory 25+ Products, variants, materials, stock levels
Orders 20+ Sales orders, purchase orders, fulfillment
Manufacturing 15+ BOMs, manufacturing orders, operations
Business Relations 10+ Customers, suppliers, addresses
Configuration 6+ Locations, webhooks, custom fields

Total: 76+ endpoints with 150+ fully-typed data models.

๐ŸŽฏ Why KatanaClient?

Automatic Resilience

Every API call through KatanaClient automatically includes:

  • Smart Retries: Exponential backoff (1s, 2s, 4s, 8s, 16s) for network errors and server errors
  • Rate Limit Handling: All HTTP methods (including POST/PATCH) are automatically retried on 429 errors with Retry-After header support
  • Idempotent Server Error Retry: Only safe methods (GET, PUT, DELETE) are retried on 502/503/504 errors
  • Error Recovery: Intelligent retry logic that doesn't retry other 4xx client errors
  • Observability: Rich logging for debugging and monitoring

Pythonic Design

# No decorators, no wrapper methods needed
async with KatanaClient() as client:
    # Just use the generated API methods directly
    response = await get_all_products.asyncio_detailed(
        client=client,
        limit=100
    )
    # Automatic retries, rate limiting, logging - all transparent!

Transport-Layer Architecture

Uses httpx's native transport layer for resilience - the most pythonic approach:

  • Zero Dependencies: Built on httpx's standard extension points
  • Maximum Compatibility: Works with any httpx-based code
  • Easy Testing: Simple to mock and test
  • Performance: Minimal overhead compared to decorators

๐Ÿ”ง Advanced Usage

Custom Configuration

import logging

from katana_public_api_client import KatanaClient

# Custom configuration
async with KatanaClient(
    api_key="custom-key",
    base_url="https://custom.katana.com/v1",
    timeout=60.0,
    max_retries=3,
    logger=logging.getLogger("katana")
) as client:
    # Your API calls here
    pass

Automatic Pagination

from katana_public_api_client import KatanaClient
from katana_public_api_client.api.product import get_all_products

async with KatanaClient() as client:
    # Get all products with automatic pagination
    all_products_response = await get_all_products.asyncio_detailed(
        client=client,
        is_sellable=True
    )
    sellable_products = all_products_response.parsed.data
    print(f"Found {len(sellable_products)} sellable products")

Response Unwrapping Utilities

Convenient helpers to unwrap responses and handle errors:

from katana_public_api_client import (
    KatanaClient,
    unwrap,
    unwrap_data,
    APIError,
    AuthenticationError,
    ValidationError,
)
from katana_public_api_client.api.product import get_all_products

async with KatanaClient() as client:
    # unwrap() extracts parsed data and raises typed exceptions on errors
    response = await get_all_products.asyncio_detailed(client=client)
    product_list = unwrap(response)  # Raises APIError on failure

    # unwrap_data() directly extracts the .data field from list responses
    products = unwrap_data(response)  # Returns list of Product objects
    for product in products:
        print(f"Product: {product.name}")

    # Handle errors with typed exceptions
    try:
        response = await get_all_products.asyncio_detailed(client=client)
        products = unwrap(response)
    except AuthenticationError as e:
        print(f"Auth failed: {e}")
    except ValidationError as e:
        print(f"Validation error: {e.validation_errors}")
    except APIError as e:
        print(f"API error {e.status_code}: {e}")

See examples/using_utils.py for more examples.

๐Ÿ“ Project Structure

This is a monorepo managed with uv workspace, containing multiple packages:

katana-openapi-client/           # Repository root (workspace)
โ”œโ”€โ”€ pyproject.toml               # Workspace configuration
โ”œโ”€โ”€ uv.lock                      # Unified lock file for all packages
โ”œโ”€โ”€ docs/katana-openapi.yaml     # OpenAPI 3.1.0 specification
โ”œโ”€โ”€ katana_public_api_client/    # Main package - Generated Python client
โ”‚   โ”œโ”€โ”€ katana_client.py         # KatanaClient with transport-layer resilience
โ”‚   โ”œโ”€โ”€ client.py                # Base generated client classes
โ”‚   โ”œโ”€โ”€ api/                     # 76+ API endpoint modules
โ”‚   โ”œโ”€โ”€ models/                  # 150+ data models
โ”‚   โ””โ”€โ”€ types.py                 # Type definitions
โ”œโ”€โ”€ katana_mcp_server/           # MCP server package (coming soon)
โ”‚   โ””โ”€โ”€ pyproject.toml           # Package-specific configuration
โ”œโ”€โ”€ docs/                        # Documentation
โ”œโ”€โ”€ tests/                       # Test suite
โ””โ”€โ”€ scripts/                     # Development utilities

The workspace configuration enables:

  • Unified dependency management across packages
  • Version compatibility guarantees
  • Single lock file for reproducible builds
  • Parallel development of client and server

See ADR-010 for architectural details.

๐Ÿงช Testing

# Run all tests
uv run poe test

# Run with coverage
uv run poe test-coverage

# Run specific test categories
uv run poe test-unit           # Unit tests only
uv run poe test-integration    # Integration tests only

๐Ÿ“š Documentation

User Guides

Architecture & Design

Project Analysis

๐Ÿ”„ Development Workflow

Development Setup

# Install dependencies
uv sync --all-extras

# Install pre-commit hooks (important!)
uv run poe pre-commit-install

# See all available tasks
uv run poe help

# Quick development check
uv run poe check

# Auto-fix common issues
uv run poe fix

Code Quality Tasks

# Formatting
uv run poe format              # Format all code and documentation
uv run poe format-check        # Check formatting without changes
uv run poe format-python       # Format Python code only

# Linting and Type Checking
uv run poe lint                 # Run all linters (ruff, mypy, yaml)
uv run poe lint-ruff           # Fast linting with ruff
uv run poe lint-mypy           # Type checking with mypy

# Testing
uv run poe test                 # Run all tests
uv run poe test-coverage       # Run tests with coverage
uv run poe test-unit           # Unit tests only
uv run poe test-integration    # Integration tests only

OpenAPI and Client Generation

# Regenerate client from OpenAPI spec
uv run poe regenerate-client

# Validate OpenAPI specification
uv run poe validate-openapi

# Full preparation workflow
uv run poe prepare             # Format + lint + test + validate

Pre-commit Hooks

# Install pre-commit hooks (run once after clone)
uv run poe pre-commit-install

# Run pre-commit on all files manually
uv run poe pre-commit-run

# Update pre-commit hook versions
uv run poe pre-commit-update

CI/Development Workflows

# Full CI pipeline (what runs in GitHub Actions)
uv run poe ci

# Pre-commit preparation
uv run poe prepare

# Clean build artifacts
uv run poe clean

Configuration

All tool configurations are consolidated in pyproject.toml following modern Python packaging standards:

  • uv: Fast, modern package and dependency manager
  • Hatchling: Build backend for package distribution
  • Ruff: Code formatting and linting (replaces Black, isort, flake8)
  • MyPy: Type checking configuration
  • Pytest: Test discovery and execution settings
  • Coverage: Code coverage reporting
  • Poe: Task automation and scripts
  • Semantic Release: Automated versioning and releases

๐Ÿ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿค Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

katana_openapi_client-0.30.0.tar.gz (763.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

katana_openapi_client-0.30.0-py3-none-any.whl (785.7 kB view details)

Uploaded Python 3

File details

Details for the file katana_openapi_client-0.30.0.tar.gz.

File metadata

  • Download URL: katana_openapi_client-0.30.0.tar.gz
  • Upload date:
  • Size: 763.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for katana_openapi_client-0.30.0.tar.gz
Algorithm Hash digest
SHA256 9f520fb1ab24cae6e15ff064d38bf72daea86df9f29dc029cded00dcd7c68c3a
MD5 7e73b5eca018ddc0387522a21d7d522e
BLAKE2b-256 242d926427d63e9a810152af0054a3aaa4a2bb323b9bdd60bec362290ebe94ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for katana_openapi_client-0.30.0.tar.gz:

Publisher: release.yml on dougborg/katana-openapi-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file katana_openapi_client-0.30.0-py3-none-any.whl.

File metadata

File hashes

Hashes for katana_openapi_client-0.30.0-py3-none-any.whl
Algorithm Hash digest
SHA256 41d94b121e89986a4a3a022eaee7e518ef84780bdbb4fe1354c917c2c764b21e
MD5 ea36e3b9b84807bc02891c22c28afde9
BLAKE2b-256 1347639785c9223f4b9a4b66a2affce27d4f7cf9a06695f81a81c93e5becf0a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for katana_openapi_client-0.30.0-py3-none-any.whl:

Publisher: release.yml on dougborg/katana-openapi-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page