This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a modern Python client library for the Kubera Data API v3. It provides both synchronous and asynchronous interfaces for interacting with Kubera portfolio data, with full type hints and comprehensive error handling.
pip install -e ".[dev]"pip install git+https://github.com/the-mace/kubera-python-api.gitCredentials are loaded from ~/.env:
KUBERA_API_KEY=your_api_key
KUBERA_SECRET=your_secretpytest # Run all tests
pytest -v # Verbose output
pytest --cov=kubera # With coverage reportruff check . # Lint code
ruff format . # Format code
mypy kubera # Type checking# Python examples
python examples/basic_usage.py
python examples/async_usage.py
python examples/context_manager.py
# CLI examples
kubera list
kubera show <portfolio-id>
kubera interactivekubera-python-api/
├── kubera/ # Main package
│ ├── __init__.py # Package exports
│ ├── client.py # KuberaClient implementation
│ ├── cli.py # Command-line interface
│ ├── formatters.py # CLI output formatters
│ ├── auth.py # HMAC-SHA256 authentication
│ ├── types.py # TypedDict definitions
│ └── exceptions.py # Custom exceptions
├── examples/ # Usage examples
│ ├── *.py # Python library examples
│ └── cli_usage.md # CLI documentation
├── tests/ # Test suite
├── pyproject.toml # Modern Python packaging
└── README.md # User documentation
The package includes a kubera CLI command installed via the [project.scripts] entry point.
kubera list- List all portfolioskubera show <id>- Show detailed portfolio informationkubera update <id>- Update an asset or debt itemkubera interactive- Interactive exploration mode
- Human-readable output using Rich library for tables and colors
--rawflag for JSON output (useful for scripting)--treeflag for hierarchical tree view- Lazy client initialization (only connects when needed)
- Uses HMAC-SHA256 signature-based authentication
- Signature generation:
HMAC(api_key + timestamp + method + path + body, secret) - Three headers required:
x-api-token,x-timestamp,x-signature - Body must be compact JSON (no spaces) for signature calculation
- Dual API: Both sync and async methods (async methods prefixed with
a) - Context Managers: Supports both
withandasync withfor automatic cleanup - Error Handling: Custom exception hierarchy for different error types
- Type Safety: Full type hints using
TypedDictfor API responses
client.py - Main client class
KuberaClient: Primary interface with sync/async methodsget_portfolios()/aget_portfolios(): List all portfoliosget_portfolio(id)/aget_portfolio(id): Get portfolio detailsupdate_item(id, updates)/aupdate_item(id, updates): Update assets/debts
auth.py - Authentication utilities
generate_signature(): Creates HMAC-SHA256 signaturecreate_auth_headers(): Generates complete auth headers
types.py - Type definitions
PortfolioSummary: Portfolio list response typePortfolioData: Detailed portfolio response typeUpdateItemRequest: Item update request typeValueDict,ConnectionDict,ItemData: Nested data structures
exceptions.py - Exception hierarchy
KuberaAPIError: Base exceptionKuberaAuthenticationError: Auth failures (401)KuberaRateLimitError: Rate limit exceeded (429)KuberaValidationError: Invalid requests (400)
cli.py - Command-line interface
cli(): Main Click group with credential handlingget_client(): Lazy client initializationlist(),show(),update(),interactive(): CLI commands
formatters.py - Output formatting
print_portfolios(): Format portfolio list with Rich tablesprint_portfolio(): Format detailed portfolio viewprint_asset_tree(): Hierarchical tree viewprint_item(),print_success(),print_error(): Utility formatters
All endpoints use https://api.kubera.com as base URL:
- GET
/api/v3/data/portfolio- List all portfolios - GET
/api/v3/data/portfolio/{id}- Get portfolio details - POST
/api/v3/data/item/{id}- Update asset/debt item (requires update permissions)
Update Permissions:
- The POST
/api/v3/data/item/{id}endpoint requires API keys with update permissions - Read-only API keys will receive 403 Forbidden errors on update attempts
- List and show operations work with read-only keys
IP Address Restrictions:
- Some API keys may be restricted to specific IP addresses
- 401 Authentication errors may indicate IP address not in allowlist
- Users should verify their IP is allowed if seeing authentication failures
- 30 requests per minute (global limit)
- Essential tier: 100 requests/day (UTC)
- Black tier: 1000 requests/day (UTC)
- Invalid API key or secret
- IP address not in allowlist (if IP restrictions enabled)
- Error messages include hints about checking credentials and IP restrictions
- Attempting updates with read-only API key
- API key lacks required permissions for operation
- Error messages explain update permission requirements
- Exceeded requests per minute or daily limits
- Error messages include current rate limit information
- Add method signature to
KuberaClientinclient.py - Implement both sync and async versions
- Add type definitions to
types.pyif needed - Update error handling in
_handle_response()if needed - Add example usage to
examples/ - Update README.md with new method documentation
- Use
TypedDictfor API response structures - Use
total=Falsefor optional fields - All functions must have complete type annotations
- Run
mypy kuberato verify type correctness
- Use
pytestfor all tests - Use
pytest-asynciofor async test support - Mock HTTP requests using
httpxtest utilities - Aim for >90% code coverage
- Follow PEP 8 (enforced by Ruff)
- Line length: 100 characters
- Use Ruff for formatting and linting
- Docstrings required for all public methods
- Always run the lint and unit tests before pushing any code. Squash merges on branches too.
- Always include claude.md changes with commits when it has been updated