Metadata-Version: 2.4
Name: wandelbots_api_client
Version: 26.2.0.dev52
Summary: Wandelbots Python Client: Interact with robots in an easy and intuitive way. 
Home-page: 
Author: Copyright (c) 2025 Wandelbots GmbH
Author-email: "Copyright (c) 2025 Wandelbots GmbH" <contact@wandelbots.com>
License-Expression: Apache-2.0
Project-URL: homepage, https://wandelbots.com/
Classifier: Typing :: Typed
Classifier: Topic :: Software Development
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Operating System :: Unix
Classifier: Operating System :: MacOS
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: urllib3>=1.25.3
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: aiohttp>=3.8.4
Requires-Dist: aiohttp-retry>=2.8.3
Requires-Dist: pydantic>=2
Requires-Dist: websockets
Requires-Dist: typing-extensions>=4.7.1
Requires-Dist: furl
Requires-Dist: pyhumps
Requires-Dist: pydantic_core
Requires-Dist: annotated-types
Requires-Dist: pydantic[email]
Provides-Extra: dev
Requires-Dist: pytest>=7.2.1; extra == "dev"
Requires-Dist: tox>=3.9.0; extra == "dev"
Requires-Dist: flake8>=4.0.0; extra == "dev"
Requires-Dist: types-python-dateutil>=2.8.19.14; extra == "dev"
Requires-Dist: mypy==1.4.1; extra == "dev"
Dynamic: author
Dynamic: license-file

# wandelbots-api-client
Interact with robots in an easy and intuitive way.

- Compatible API version: 1.3.0 dev (can be found at the home screen of your instance -> API)
- Package version: 26.2.0.dev52

## Requirements.
Python >=3.11, Python < 4.0

## Installation

```bash
pip install wandelbots-api-client
```

OR with uv:

```bash
uv init
uv add wandelbots-api-client
```

## Authentication

The SDK supports OAuth2 device code flow authentication for both Entra ID (formerly Azure AD) and Auth0. This authentication method is ideal for CLI applications, scripts, and headless environments.

### Entra ID (Azure AD) Authentication

```python
import asyncio
from wandelbots_api_client import ApiClient, Configuration
from wandelbots_api_client.authorization import EntraIDConfig

async def main():
    # Initialize Entra ID config
    auth = EntraIDConfig(
        client_id="GIVEN_CLIENT_ID",
        tenant_id="GIVEN_TENANT_ID", 
        scope="openid profile email offline_access GIVEN_CLIENT_ID\.default"
    )
    
    # Request device code
    device_response = await auth.request_device_code()
    
    # Display user instructions
    print(f"\nPlease authenticate:")
    print(f"1. Go to: {device_response['verification_uri']}")
    print(f"2. Enter code: {device_response['user_code']}")
    print(f"Waiting for authentication...\n")
    
    # Poll for token (will wait until user completes authentication)
    token_response = await auth.poll_token_endpoint(
        device_code=device_response["device_code"],
        interval=device_response.get("interval", 5),
        expires_in=device_response.get("expires_in", 900)
    )
    
    print("Authentication successful!")
    
    # Configure API client with access token
    config = Configuration(
        host="https://your-instance.wandelbots.io",
        access_token=token_response["access_token"]
    )
    
    async with ApiClient(configuration=config) as api_client:
        # Use the API client for authenticated requests
        # Example: api = YourApi(api_client)
        # result = await api.your_method()
        pass
    
    # Optionally refresh the token later
    if "refresh_token" in token_response:
        new_token = await auth.refresh_token(token_response["refresh_token"])
        config.access_token = new_token["access_token"]

asyncio.run(main())
```

### Auth0 Authentication

```python
import asyncio
from wandelbots_api_client import ApiClient, Configuration
from wandelbots_api_client.authorization import Auth0Config

async def main():
    # Initialize Auth0 config
    auth = Auth0Config(
        client_id="GIVEN_CLIENT_ID",
        domain="auth.portal.wandelbots.io",
        audience="GIVEN_AUDIENCE", 
        scope="openid profile email offline_access"
    )
    
    # Or use default config from template variables
    # auth = Auth0Config.default()
    
    # Request device code
    device_response = await auth.request_device_code()
    
    # Display user instructions
    print(f"\nPlease authenticate:")
    print(f"1. Go to: {device_response['verification_uri']}")
    print(f"2. Enter code: {device_response['user_code']}")
    print(f"Waiting for authentication...\n")
    
    # Poll for token (will wait until user completes authentication)
    token_response = await auth.poll_token_endpoint(
        device_code=device_response["device_code"],
        interval=device_response.get("interval", 5),
        expires_in=device_response.get("expires_in", 900)
    )
    
    print("Authentication successful!")
    
    # Configure API client with access token
    config = Configuration(
        host="https://XYZ.instances.wandelbots.io",
        access_token=token_response["access_token"]
    )
    
    async with ApiClient(configuration=config) as api_client:
        # Use the API client for authenticated requests
        # Example: api = YourApi(api_client)
        # result = await api.your_method()
        pass

asyncio.run(main())
```

### Token Refresh

To maintain long-lived sessions, use refresh tokens to obtain new access tokens:

```python
# When your access token expires
if "refresh_token" in token_response:
    refreshed = await auth.refresh_token(token_response["refresh_token"])
    config.access_token = refreshed["access_token"]
    
    # Update refresh token if a new one is provided
    if "refresh_token" in refreshed:
        token_response["refresh_token"] = refreshed["refresh_token"]
```

### Complete Example with Error Handling

```python
import asyncio
from wandelbots_api_client import ApiClient, Configuration
from wandelbots_api_client.authorization import EntraIDConfig

async def authenticate_and_call_api():
    """Complete example with error handling."""
    try:
        # Initialize authentication
        auth = EntraIDConfig(
            client_id="GIVEN_CLIENT_ID",
            tenant_id="GIVEN_TENANT_ID",
            scopen="openid profile email offline_access GIVEN_CLIENT_ID\.default"
        )
        
        # Verify configuration
        if not auth.is_complete():
            raise ValueError("Authentication configuration is incomplete")
        
        # Request device code
        device_response = await auth.request_device_code()
        
        # Display instructions
        print(f"\n{'='*60}")
        print(f"AUTHENTICATION REQUIRED")
        print(f"{'='*60}")
        print(f"Visit: {device_response['verification_uri']}")
        print(f"Enter code: {device_response['user_code']}")
        print(f"{'='*60}\n")
        
        # Wait for user to authenticate
        token_response = await auth.poll_token_endpoint(
            device_code=device_response["device_code"],
            interval=device_response.get("interval", 5),
            expires_in=device_response.get("expires_in", 900)
        )
        
        print("✓ Authentication successful!\n")
        
        # Create API client
        config = Configuration(
            host="https://XYZ.instance.wandelbots.io",
            access_token=token_response["access_token"]
        )
        
        async with ApiClient(configuration=config) as api_client:
            # Make authenticated API calls here
            # Example:
            # from wandelbots_api_client.api import YourApi
            # api = YourApi(api_client)
            # result = await api.your_method()
            print("API client ready for requests")
            
    except TimeoutError:
        print("Authentication timed out. Please try again.")
    except ValueError as e:
        print(f"Configuration error: {e}")
    except Exception as e:
        print(f"Authentication failed: {e}")

asyncio.run(authenticate_and_call_api())
```


