# Python SDK

This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project.

## Requirements

Python 3.11+

## Installation

**Using pip**
```bash
pip install catapa
```

**Using poetry**
```bash
poetry add catapa
```

**Using uv**
```bash
uv add catapa
```

## Quick Start

A complete Hello World example to get you started immediately.

```python
from catapa import Catapa, EmployeeApi

client = Catapa(tenant="zfrl", client_id="demo", client_secret="demo-secret")
employee_api = EmployeeApi(client)

# Get employees. The client automatically handles OAuth2 authentication and token refresh
employees = employee_api.list_all_employees(page=0, size=10)

print(f"Found {len(employees.content)} employees")
```

> **💡 Tip:** By default, the SDK connects to `https://api.catapa.com`. To use a different base URL (e.g., for staging or testing), pass the `base_url` parameter:
> ```python
> client = Catapa(
>     tenant="your-tenant",
>     client_id="your-client-id",
>     client_secret="your-client-secret",
>     base_url="https://staging-api.catapa.com"  # Optional: override default base URL
> )
> ```

## Getting Your Credentials

To use the SDK with your own account, you'll need the following authentication credentials:

### Tenant ID

Your **tenant ID** is your organization's unique identifier in CATAPA. To obtain it, please contact [support@catapa.com](mailto:support@catapa.com).

### Client ID and Client Secret

Your **client ID** and **client secret** are OAuth2 credentials used to authenticate your application.

Get them from: [https://apps.catapa.com/dashboard/setup/settings/oauth-client](https://apps.catapa.com/dashboard/setup/settings/oauth-client)

> **⚠️ Important:** Keep your client secret secure and never commit it to version control. Consider using environment variables or a secrets management system.

## Tutorials

More intermediate examples to help you learn the SDK.

### Tutorial 1: Using Multiple APIs

A complete example showing how to use multiple API classes with a single client.

```python
#!/usr/bin/env python3

from catapa import Catapa, OrganizationApi, MasterDataApi

def main() -> None:
    """Main function demonstrating multiple API usage."""
    # Initialize client once
    client = Catapa(tenant="zfrl", client_id="demo", client_secret="demo-secret")

    # Use different APIs with the same client
    org_api = OrganizationApi(client)
    company = org_api.get_companies()
    print(f"Company: {company.content[0].name}")

    master_data_api = MasterDataApi(client)
    countries = master_data_api.get_countries()
    print(f"Countries available: {len(countries.content)}")

if __name__ == "__main__":
    main()
```

## Cookbook

Intermediate to Advanced examples for real-world scenarios.

### Cookbook 1: Long-Running Services

A complete example for long-running services that need persistent API access.

```python
#!/usr/bin/env python3

from catapa import Catapa, EmployeeApi
import time

def main() -> None:
    """Main function for long-running service example."""
    # Initialize client once at service startup
    client = Catapa(tenant="zfrl", client_id="demo", client_secret="demo-secret")
    employee_api = EmployeeApi(client)

    # Make an API call
    employees = employee_api.list_all_employees(page=0, size=10)
    print(f"Initial call: {len(employees.content)} employees")

    # Simulate long-running service (e.g., wait an hour)
    # In real scenarios, this could be a loop, scheduled task, or event handler
    print("Service running... (simulating 1 hour wait)")
    time.sleep(3600)

    employees = employee_api.list_all_employees(page=0, size=10)
    print(f"After 1 hour: {len(employees.content)} employees")
    print("✅ Token was automatically refreshed if needed!")

if __name__ == "__main__":
    main()
```

### Cookbook 2: Concurrent API Calls

A complete example for making concurrent API calls efficiently.

```python
#!/usr/bin/env python3

from catapa import Catapa, EmployeeApi, OrganizationApi, MasterDataApi
from concurrent.futures import ThreadPoolExecutor, as_completed

def main() -> None:
    """Main function for concurrent API calls example."""
    client = Catapa(tenant="zfrl", client_id="demo", client_secret="demo-secret")

    # Create API instances
    employee_api = EmployeeApi(client)
    org_api = OrganizationApi(client)
    master_data_api = MasterDataApi(client)

    # Define API call functions
    def get_employees():
        return employee_api.list_all_employees(page=0, size=10)

    def get_organization():
        return org_api.get_companies()

    def get_countries():
        return master_data_api.get_countries()

    # Execute API calls concurrently
    with ThreadPoolExecutor(max_workers=3) as executor:
        futures = {
            executor.submit(get_employees): "employees",
            executor.submit(get_organization): "organization",
            executor.submit(get_countries): "countries"
        }

        results = {}
        for future in as_completed(futures):
            task_name = futures[future]
            try:
                results[task_name] = future.result()
                print(f"✅ {task_name} retrieved successfully")
            except Exception as e:
                print(f"❌ {task_name} failed: {e}")

    # Use the results
    if "employees" in results:
        print(f"Employees: {len(results['employees'].content)}")
    if "organization" in results:
        print(f"Organization: {results['organization'].content[0].name}")
    if "countries" in results:
        print(f"Countries: {len(results['countries'].content)}")


if __name__ == "__main__":
    main()
```

## Available APIs

All CATAPA APIs are available through the `catapa` package:

```python
from catapa import (
    Catapa,
    EmployeeApi,
    OrganizationApi,
    MasterDataApi,
    TaxApi,
    SalaryPaymentApi,
    PayrollProcessSnapshotApi,
    # ... and 40+ more APIs
)
```