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.
โจ 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):
- Direct parameter: Pass
api_keytoKatanaClient() - Environment variable: Set
KATANA_API_KEY .envfile: Create a.envfile with your credentials~/.netrcfile: 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-Afterheader 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
- Cookbook - Practical recipes for common integration scenarios
- KatanaClient Guide - Complete KatanaClient usage guide
- API Reference - Generated API documentation
- Migration Guide - Upgrading from previous versions
- Testing Guide - Testing patterns and examples
Architecture & Design
- Architecture Decision Records (ADRs) - Key architectural decisions
Project Analysis
- Revised Assessment - Comprehensive review (Grade: A, 95/100)
- Coverage Analysis - Test coverage breakdown (74.8% core logic)
- Builder Pattern Analysis - Builder vs domain helpers
- Domain Helpers Design - Complete helper design
๐ 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, ty, yaml)
uv run poe lint-ruff # Fast linting with ruff
uv run poe typecheck # Type checking with ty
# 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file katana_openapi_client-0.37.0.tar.gz.
File metadata
- Download URL: katana_openapi_client-0.37.0.tar.gz
- Upload date:
- Size: 925.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aac890585933a2077157579cf0ba29244180fba0ed4dd759c2a2dbd589b30894
|
|
| MD5 |
ff40dc9898ddff7eaf92e24678de0e7c
|
|
| BLAKE2b-256 |
a5c61d3510d22e68f8076f7888c9a15e80ac64866afe69a80cd1c6fc9a2172d9
|
Provenance
The following attestation bundles were made for katana_openapi_client-0.37.0.tar.gz:
Publisher:
release.yml on dougborg/katana-openapi-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
katana_openapi_client-0.37.0.tar.gz -
Subject digest:
aac890585933a2077157579cf0ba29244180fba0ed4dd759c2a2dbd589b30894 - Sigstore transparency entry: 742243140
- Sigstore integration time:
-
Permalink:
dougborg/katana-openapi-client@8dc3cfcb1e9751b2c204a709846bee9dd1cc9eea -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dougborg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8dc3cfcb1e9751b2c204a709846bee9dd1cc9eea -
Trigger Event:
push
-
Statement type:
File details
Details for the file katana_openapi_client-0.37.0-py3-none-any.whl.
File metadata
- Download URL: katana_openapi_client-0.37.0-py3-none-any.whl
- Upload date:
- Size: 813.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af213110da8b0fc77a9e2f872fe13d8ddf51836ca47d0f7cf12fc57c409eb1bf
|
|
| MD5 |
79b559c3b2738cdc889e22143827c9ca
|
|
| BLAKE2b-256 |
3787957f1643e0e96e8584a7c0b8eee5a1c146b989928c400540ee52ca878772
|
Provenance
The following attestation bundles were made for katana_openapi_client-0.37.0-py3-none-any.whl:
Publisher:
release.yml on dougborg/katana-openapi-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
katana_openapi_client-0.37.0-py3-none-any.whl -
Subject digest:
af213110da8b0fc77a9e2f872fe13d8ddf51836ca47d0f7cf12fc57c409eb1bf - Sigstore transparency entry: 742243176
- Sigstore integration time:
-
Permalink:
dougborg/katana-openapi-client@8dc3cfcb1e9751b2c204a709846bee9dd1cc9eea -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dougborg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8dc3cfcb1e9751b2c204a709846bee9dd1cc9eea -
Trigger Event:
push
-
Statement type: