katana_public_api_client.katana_client¶
katana_public_api_client.katana_client
¶
KatanaClient - The pythonic Katana API client with automatic resilience.
This client uses httpx's native transport layer to provide automatic retries, rate limiting, error handling, and pagination for all API calls without any decorators or wrapper methods needed.
Classes¶
ErrorLoggingTransport(wrapped_transport=None, logger=None, **kwargs)
¶
Bases: AsyncHTTPTransport
Transport layer that adds detailed error logging for 4xx client errors.
This transport wraps another AsyncHTTPTransport and intercepts responses to log detailed error information using the generated error models.
Parameters:
-
wrapped_transport(AsyncHTTPTransport | None, default:None) –The transport to wrap. If None, creates a new AsyncHTTPTransport.
-
logger(Logger | None, default:None) –Logger instance for capturing error details. If None, creates a default logger.
-
**kwargs(Any, default:{}) –Additional arguments passed to AsyncHTTPTransport if wrapped_transport is None.
Source code in katana_public_api_client/katana_client.py
Functions¶
handle_async_request(request)
async
¶
Handle request and log detailed error information for 4xx responses.
Source code in katana_public_api_client/katana_client.py
KatanaClient(api_key=None, base_url=None, timeout=30.0, max_retries=5, max_pages=100, logger=None, **httpx_kwargs)
¶
Bases: AuthenticatedClient
The pythonic Katana API client with automatic resilience and pagination.
This client inherits from AuthenticatedClient and can be passed directly to generated API methods without needing the .client property.
Features: - Automatic retries on network errors and server errors (5xx) - Automatic rate limit handling with Retry-After header support - Smart auto-pagination that detects and handles paginated responses automatically - Rich logging and observability - Minimal configuration - just works out of the box
Usage
Auto-pagination happens automatically - just call the API¶
async with KatanaClient() as client: from katana_public_api_client.api.product import get_all_products
# This automatically collects all pages if pagination is detected
response = await get_all_products.asyncio_detailed(
client=client, # Pass client directly - no .client needed!
limit=50 # All pages collected automatically
)
# Get specific page only (add page=X to disable auto-pagination)
response = await get_all_products.asyncio_detailed(
client=client,
page=1, # Get specific page
limit=100 # Set page size
)
# Control max pages globally
client_limited = KatanaClient(max_pages=5) # Limit to 5 pages max
Parameters:
-
api_key(str | None, default:None) –Katana API key. If None, will try to load from KATANA_API_KEY env var, .env file, or ~/.netrc file (in that order).
-
base_url(str | None, default:None) –Base URL for the Katana API. Defaults to https://api.katanamrp.com/v1
-
timeout(float, default:30.0) –Request timeout in seconds. Defaults to 30.0.
-
max_retries(int, default:5) –Maximum number of retry attempts for failed requests. Defaults to 5.
-
max_pages(int, default:100) –Maximum number of pages to collect during auto-pagination. Defaults to 100.
-
logger(Logger | None, default:None) –Logger instance for capturing client operations. If None, creates a default logger.
-
**httpx_kwargs(Any, default:{}) –Additional arguments passed to the base AsyncHTTPTransport. Common parameters include: - http2 (bool): Enable HTTP/2 support - limits (httpx.Limits): Connection pool limits - verify (bool | str | ssl.SSLContext): SSL certificate verification - cert (str | tuple): Client-side certificates - trust_env (bool): Trust environment variables for proxy configuration - event_hooks (dict): Custom event hooks (will be merged with built-in hooks)
Raises:
-
ValueError–If no API key is provided via api_key param, KATANA_API_KEY env var, .env file, or ~/.netrc file.
Note
Transport-related parameters (http2, limits, verify, etc.) are correctly passed to the innermost AsyncHTTPTransport layer, ensuring they take effect even with the layered transport architecture.
Example
async with KatanaClient() as client: ... # All API calls through client get automatic resilience ... response = await some_api_method.asyncio_detailed(client=client)
Source code in katana_public_api_client/katana_client.py
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | |
Attributes¶
inventory
property
¶
Access inventory and stock operations.
Returns:
-
Inventory–Inventory instance for stock levels, movements, and adjustments.
Example
async with KatanaClient() as client: ... # Check stock levels ... stock = await client.inventory.check_stock("WIDGET-001") ... low_stock = await client.inventory.list_low_stock(threshold=10)
materials
property
¶
Access material catalog operations.
Returns:
-
Materials–Materials instance for material CRUD operations.
Example
async with KatanaClient() as client: ... materials = await client.materials.list() ... material = await client.materials.get(123)
products
property
¶
Access product catalog operations.
Returns:
-
Products–Products instance for product CRUD and search operations.
Example
async with KatanaClient() as client: ... # Product CRUD ... products = await client.products.list(is_sellable=True) ... product = await client.products.get(123) ... results = await client.products.search("widget")
services
property
¶
Access service catalog operations.
Returns:
-
Services–Services instance for service CRUD operations.
Example
async with KatanaClient() as client: ... services = await client.services.list() ... service = await client.services.get(123)
variants
property
¶
Access variant catalog operations.
Returns:
-
Variants–Variants instance for variant CRUD operations.
Example
async with KatanaClient() as client: ... variants = await client.variants.list() ... variant = await client.variants.get(123)
Functions¶
PaginationTransport(wrapped_transport=None, max_pages=100, logger=None, **kwargs)
¶
Bases: AsyncHTTPTransport
Transport layer that adds automatic pagination for GET requests.
This transport wraps another transport and automatically collects all pages for requests that use 'page' or 'limit' parameters.
Parameters:
-
wrapped_transport(AsyncHTTPTransport | None, default:None) –The transport to wrap. If None, creates a new AsyncHTTPTransport.
-
max_pages(int, default:100) –Maximum number of pages to collect during auto-pagination. Defaults to 100.
-
logger(Logger | None, default:None) –Logger instance for capturing pagination operations. If None, creates a default logger.
-
**kwargs(Any, default:{}) –Additional arguments passed to AsyncHTTPTransport if wrapped_transport is None.
Source code in katana_public_api_client/katana_client.py
Functions¶
handle_async_request(request)
async
¶
Handle request with automatic pagination for GET requests with page/limit params.
Source code in katana_public_api_client/katana_client.py
RateLimitAwareRetry(*args, **kwargs)
¶
Bases: Retry
Custom Retry class that allows non-idempotent methods (POST, PATCH) to be retried ONLY when receiving a 429 (Too Many Requests) status code.
For all other retryable status codes (502, 503, 504), only idempotent methods (HEAD, GET, PUT, DELETE, OPTIONS, TRACE) will be retried.
This ensures we don't accidentally retry non-idempotent operations after server errors, but we DO retry them when we're being rate-limited.
Source code in katana_public_api_client/katana_client.py
Functions¶
increment()
¶
Return a new retry instance with the attempt count incremented.
Source code in katana_public_api_client/katana_client.py
is_retryable_method(method)
¶
Allow all methods to pass through the initial check.
Store the method for later use in is_retryable_status_code.
Source code in katana_public_api_client/katana_client.py
is_retryable_status_code(status_code)
¶
Check if a status code is retryable for the current method.
For 429 (rate limiting), allow all methods. For other errors (502, 503, 504), only allow idempotent methods.
Source code in katana_public_api_client/katana_client.py
Functions¶
ResilientAsyncTransport(max_retries=5, max_pages=100, logger=None, **kwargs)
¶
Factory function that creates a chained transport with error logging, pagination, and retry capabilities.
This function chains multiple transport layers: 1. AsyncHTTPTransport (base HTTP transport) 2. ErrorLoggingTransport (logs detailed 4xx errors) 3. PaginationTransport (auto-collects paginated responses) 4. RetryTransport (handles retries with Retry-After header support)
Parameters:
-
max_retries(int, default:5) –Maximum number of retry attempts for failed requests. Defaults to 5.
-
max_pages(int, default:100) –Maximum number of pages to collect during auto-pagination. Defaults to 100.
-
logger(Logger | None, default:None) –Logger instance for capturing operations. If None, creates a default logger.
-
**kwargs(Any, default:{}) –Additional arguments passed to the base AsyncHTTPTransport. Common parameters include: - http2 (bool): Enable HTTP/2 support - limits (httpx.Limits): Connection pool limits - verify (bool | str | ssl.SSLContext): SSL certificate verification - cert (str | tuple): Client-side certificates - trust_env (bool): Trust environment variables for proxy configuration
Returns:
-
RetryTransport–A RetryTransport instance wrapping all the layered transports.
Note
When using a custom transport, parameters like http2, limits, and verify must be passed to this factory function (which passes them to the base AsyncHTTPTransport), not to the httpx.Client/AsyncClient constructor.
Example
Source code in katana_public_api_client/katana_client.py
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | |