Metadata-Version: 2.4
Name: wex-health-sdk
Version: 0.1.0a1
Summary: Python SDK for Wex Health and Benefits Platform APIs. Provides comprehensive access to claims, business, consumer, and administrative APIs with built-in authentication, logging, and error handling.
Author-email: "Wex Inc." <gl-sdk-support@wexinc.com>
Project-URL: Homepage, https://developer.wexinc.com
Project-URL: Repository, https://github.com/wex-benefits/health-python-sdk
Project-URL: Documentation, https://github.com/wex-benefits/health-python-sdk#readme
Project-URL: Issues, https://github.com/wex-benefits/health-python-sdk/issues
Project-URL: Changelog, https://github.com/wex-benefits/health-python-sdk/blob/main/CHANGELOG.md
Project-URL: Security, https://github.com/wex-benefits/health-python-sdk/blob/main/SECURITY.md
Keywords: OpenAPI,OpenAPI-Generator,Benefits Platform Claims API
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: urllib3<4.0.0,>=2.6.3
Requires-Dist: aiohttp>=3.13.3
Requires-Dist: aiohttp-retry>=2.8.3
Requires-Dist: pydantic<3,>=2.4.0
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: typing-extensions>=4.7.1
Provides-Extra: dev
Requires-Dist: pytest>=7.2.1; extra == "dev"
Requires-Dist: pytest-cov>=2.8.1; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: tox>=3.9.0; extra == "dev"
Requires-Dist: black>=26.3.1; extra == "dev"
Requires-Dist: flake8>=4.0.0; extra == "dev"
Requires-Dist: mypy>=1.5; extra == "dev"
Requires-Dist: types-python-dateutil>=2.8.19.14; extra == "dev"
Requires-Dist: build>=0.10.0; extra == "dev"
Requires-Dist: twine>=4.0.0; extra == "dev"
Dynamic: license-file

# wex-health-sdk
This SDK provides programmatic access to the Wex Health and Benefits Platform APIs. The platform
      encompasses various benefits management systems including HSA, FSA, HRA management, and COBRA
      coverage. The SDK enables integration with platform services for retrieving and managing
      benefits-related information based on the provided OpenAPI specification.

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

- API version: 1.0.0
- Generator version: 7.16.0
- Build package: org.openapitools.codegen.languages.PythonClientCodegen

For more information, please visit [https://developer.wexinc.com](https://developer.wexinc.com)

## Requirements

Python 3.9+

## Quick Start

Get started in minutes with this minimal example:

```python
import os
import asyncio
from wex_health import Configuration, ApiClient, ClaimsApi

async def main():
    config = Configuration(
        host=os.environ.get('API_HOST', 'https://api.example.com'),
        access_token=os.environ.get('ACCESS_TOKEN')
    )
    async with ApiClient(config) as client:
        api = ClaimsApi(client)
        claims = await api.get_claims_for_participant("person-id-123")
        print(f"Found {len(claims.claims)} claims")

asyncio.run(main())
```

For OAuth2 authentication and more examples, see the [Authentication](#authentication) section below.

## Installation & Usage

### Install from PyPI


```sh
pip install wex-health-sdk
```

### Verify Installation

After installation, verify the package is correctly installed:

```python
import wex_health
print(f"SDK Version: {wex_health.__version__}")
print(f"API Version: {wex_health.API_VERSION}")
```

### Tests

Execute `pytest` to run the tests.

## Authentication

The SDK supports multiple authentication methods:

### OAuth2 Client Credentials (Recommended)

```python
configuration = wex_health.Configuration(
    host=os.environ.get('API_HOST', 'https://api.example.com'),  # Replace with your API endpoint
    oauth2_credentials={
        'client_id': os.environ['OAUTH2_CLIENT_ID'],
        'client_secret': os.environ['OAUTH2_CLIENT_SECRET'],
        'access_token_url': os.environ.get('OAUTH2_TOKEN_URL', 'https://api.example.com/oauth/token'),
        'audience': os.environ.get('OAUTH2_AUDIENCE', 'https://api.example.com')
    }
)
```

### Bearer Token

```python
configuration = wex_health.Configuration(
    access_token=os.environ['BEARER_TOKEN']
)
```

For detailed authentication setup, see the [OAuth2 Authentication Guide](docs/OAUTH2_GUIDE.md).

## Retry Logic

The SDK implements a **layered resilience strategy** with automatic retry handling for transient failures:

### Key Features

- **Exponential Backoff with Jitter**: 500ms initial delay, 2s maximum cap
- **Smart 429 Handling**: Only retries rate limits when `Retry-After` header is present
- **Automatic Retry**: Handles 5xx errors, 408 Request Timeout automatically
- **Three-Layer Protection**: Global timeout (30s) + Retry policy (3 attempts) + Per-request timeout (30s)
- **Server-Aware**: Respects `Retry-After` headers (capped at 30 seconds)

### Default Configuration

```python
configuration = wex_health.Configuration(
    retries=3,              # Retry failed requests up to 3 times
    request_timeout=30.0,   # 30 second timeout per individual request
    overall_timeout=30.0    # 30 second global timeout for entire operation (all retries)
)
```

### Retry Behavior

The SDK automatically retries the following scenarios:

1. **5xx Server Errors**: 500, 502, 503, 504, 507, etc.
2. **408 Request Timeout**: Client timeout waiting for response
3. **429 Rate Limiting**: Only if `Retry-After` header is present
4. **Retry-After Header**: Any response with server-provided retry guidance

**Backoff Strategy**: Exponential backoff with jitter
- Initial delay: 500ms
- Maximum delay: 2 seconds
- Algorithm: Randomized jitter to prevent thundering herd

For comprehensive retry logic documentation, see the [Retry Logic Guide](docs/RETRY_LOGIC.md).

## Architecture Overview

The SDK follows a layered architecture designed for reliability, performance, and developer experience:

```
┌─────────────────────────────────────────────────────────┐
│                    Application Layer                     │
│  (Your Code: ClaimsApi, HealthApi, etc.)                │
└────────────────────┬────────────────────────────────────┘
                     │
┌────────────────────▼────────────────────────────────────┐
│                  API Client Layer                        │
│  • Request serialization                                │
│  • Response deserialization                              │
│  • Error handling                                       │
└────────────────────┬────────────────────────────────────┘
                     │
┌────────────────────▼────────────────────────────────────┐
│              HTTP Client Layer (aiohttp)                 │
│  • Connection pooling                                    │
│  • Retry logic with exponential backoff                 │
│  • Timeout management                                    │
│  • OAuth2 token management                              │
└────────────────────┬────────────────────────────────────┘
                     │
┌────────────────────▼────────────────────────────────────┐
│              Logging & Observability                     │
│  • Structured JSON logging                               │
│  • Request/response tracking                            │
│  • Error logging with sanitization                      │
└─────────────────────────────────────────────────────────┘
```

### Key Components

- **API Classes** (`ClaimsApi`, `HealthApi`): High-level interface for API operations
- **ApiClient**: Core HTTP client with connection pooling and retry logic
- **Configuration**: Centralized configuration management
- **Authentication**: OAuth2 and Bearer token support with automatic token refresh
- **Logging**: Structured logging with request/response tracking
- **Error Handling**: Comprehensive exception hierarchy for different error types

### Data Flow

1. **Request**: Your code calls an API method (e.g., `get_claim()`)
2. **Serialization**: Parameters are validated and serialized
3. **HTTP Request**: Request sent via aiohttp with retry logic
4. **Authentication**: OAuth2 token automatically refreshed if needed
5. **Response**: Response deserialized into typed DTOs
6. **Logging**: Request/response logged with correlation IDs

## Code Examples

### Example 1: Get Claims for a Participant

```python
import os
import asyncio
from wex_health import Configuration, ApiClient, ClaimsApi

async def get_participant_claims():
    config = Configuration(
        host=os.environ.get('API_HOST', 'https://api.example.com'),
        oauth2_credentials={
            'client_id': os.environ['OAUTH2_CLIENT_ID'],
            'client_secret': os.environ['OAUTH2_CLIENT_SECRET'],
            'access_token_url': os.environ.get('OAUTH2_TOKEN_URL'),
            'audience': os.environ.get('OAUTH2_AUDIENCE')
        }
    )
    
    async with ApiClient(config) as client:
        claims_api = ClaimsApi(client)
        
        # Get all claims for a participant
        person_id = "123e4567-e89b-12d3-a456-426614174000"
        claims = await claims_api.get_claims_for_participant(person_id)
        
        print(f"Found {len(claims.claims)} claims")
        for claim in claims.claims:
            print(f"Claim {claim.claim_number}: ${claim.amount}")

asyncio.run(get_participant_claims())
```

### Example 2: Get Specific Claim with Error Handling

```python
import asyncio
from wex_health import Configuration, ApiClient, ClaimsApi
from wex_health.exceptions import NotFoundException, ApiException

async def get_claim_safely():
    config = Configuration(
        host=os.environ.get('API_HOST'),
        access_token=os.environ.get('ACCESS_TOKEN')
    )
    
    async with ApiClient(config) as client:
        claims_api = ClaimsApi(client)
        person_id = "123e4567-e89b-12d3-a456-426614174000"
        claim_number = "11BPEB1210513P0000101"
        
        try:
            claim = await claims_api.get_claim(person_id, claim_number)
            print(f"Claim Status: {claim.status}")
            print(f"Amount: ${claim.amount}")
        except NotFoundException:
            print(f"Claim {claim_number} not found for person {person_id}")
        except ApiException as e:
            print(f"API Error: {e.status} - {e.reason}")

asyncio.run(get_claim_safely())
```

### Example 3: Get Receipts with Filtering

```python
import asyncio
from wex_health import Configuration, ApiClient, ClaimsApi
from datetime import datetime

async def get_recent_receipts():
    config = Configuration(
        host=os.environ.get('API_HOST'),
        oauth2_credentials={
            'client_id': os.environ['OAUTH2_CLIENT_ID'],
            'client_secret': os.environ['OAUTH2_CLIENT_SECRET'],
            'access_token_url': os.environ.get('OAUTH2_TOKEN_URL')
        }
    )
    
    async with ApiClient(config) as client:
        claims_api = ClaimsApi(client)
        person_id = "123e4567-e89b-12d3-a456-426614174000"
        
        # Get receipts for participant
        receipts = await claims_api.get_receipts_for_participant(person_id)
        
        # Filter recent receipts (last 30 days)
        thirty_days_ago = datetime.now().replace(day=1)
        recent_receipts = [
            r for r in receipts.receipts 
            if r.receipt_date and r.receipt_date >= thirty_days_ago
        ]
        
        print(f"Found {len(recent_receipts)} receipts in the last 30 days")

asyncio.run(get_recent_receipts())
```

### Example 4: Batch Operations with Correlation IDs

```python
import asyncio
import uuid
from wex_health import Configuration, ApiClient, ClaimsApi

async def batch_operations():
    config = Configuration(
        host=os.environ.get('API_HOST'),
        access_token=os.environ.get('ACCESS_TOKEN')
    )
    
    async with ApiClient(config) as client:
        claims_api = ClaimsApi(client)
        person_id = "123e4567-e89b-12d3-a456-426614174000"
        
        # Generate correlation ID for tracking
        correlation_id = str(uuid.uuid4())
        
        # Multiple operations with same correlation ID
        claims = await claims_api.get_claims_for_participant(
            person_id, 
            x_request_id=correlation_id
        )
        
        receipts = await claims_api.get_receipts_for_participant(
            person_id,
            x_request_id=correlation_id
        )
        
        payees = await claims_api.get_payees_for_participant(
            person_id,
            x_request_id=correlation_id
        )
        
        print(f"Batch operation {correlation_id} completed:")
        print(f"  Claims: {len(claims.claims)}")
        print(f"  Receipts: {len(receipts.receipts)}")
        print(f"  Payees: {len(payees.payees)}")

asyncio.run(batch_operations())
```

## Best Practices

### 1. **Use Environment Variables for Configuration**

✅ **Good:**
```python
config = Configuration(
    host=os.environ.get('API_HOST'),
    oauth2_credentials={
        'client_id': os.environ['OAUTH2_CLIENT_ID'],
        'client_secret': os.environ['OAUTH2_CLIENT_SECRET'],
        'access_token_url': os.environ.get('OAUTH2_TOKEN_URL')
    }
)
```

❌ **Avoid:**
```python
config = Configuration(
    host="https://api.example.com",
    oauth2_credentials={
        'client_id': "hardcoded_id",  # Don't hardcode credentials
        'client_secret': "hardcoded_secret"
    }
)
```

### 2. **Use Context Managers for Resource Management**

✅ **Good:**
```python
async with ApiClient(config) as client:
    api = ClaimsApi(client)
    result = await api.get_claim(...)
# Client automatically closed
```

❌ **Avoid:**
```python
client = ApiClient(config)
api = ClaimsApi(client)
result = await api.get_claim(...)
# Must manually call await client.close()
```

### 3. **Handle Exceptions Appropriately**

✅ **Good:**
```python
try:
    claim = await api.get_claim(person_id, claim_number)
except NotFoundException:
    # Handle not found case
    print("Claim not found")
except ApiException as e:
    # Handle other API errors
    logger.error(f"API error: {e.status} - {e.reason}")
except Exception as e:
    # Handle unexpected errors
    logger.exception("Unexpected error", exc_info=e)
```

### 4. **Use Correlation IDs for Request Tracking**

✅ **Good:**
```python
import uuid

correlation_id = str(uuid.uuid4())
claim = await api.get_claim(
    person_id, 
    claim_number,
    x_request_id=correlation_id  # Track this request
)
```

### 5. **Configure Timeouts Appropriately**

✅ **Good:**
```python
config = Configuration(
    host=os.environ.get('API_HOST'),
    request_timeout=30.0,    # Per-request timeout
    overall_timeout=60.0,    # Total timeout including retries
    retries=3                # Number of retry attempts
)
```

### 6. **Reuse ApiClient Instances**

✅ **Good:**
```python
async with ApiClient(config) as client:
    claims_api = ClaimsApi(client)
    health_api = HealthApi(client)
    
    # Reuse same client for multiple operations
    claims = await claims_api.get_claims_for_participant(...)
    health = await health_api.get_liveness()
```

### 7. **Leverage Type Hints for Better IDE Support**

✅ **Good:**
```python
from wex_health import ClaimDTO, ClaimsDTO

async def process_claims() -> list[ClaimDTO]:
    claims: ClaimsDTO = await api.get_claims_for_participant(person_id)
    return claims.claims
```

## Troubleshooting

### Common Issues

#### Connection Timeout
```
Error: Connection timeout after 30 seconds
```
**Solution**: Increase timeout values or check network connectivity
```python
config = Configuration(
    request_timeout=60.0,  # Increase timeout
    overall_timeout=120.0
)
```

#### Authentication Errors
```
Error: 401 Unauthorized
```
**Solution**: Verify OAuth2 credentials or access token
```python
# Check environment variables
print(os.environ.get('OAUTH2_CLIENT_ID'))  # Should not be None
```

#### Rate Limiting
```
Error: 429 Too Many Requests
```
**Solution**: SDK automatically retries with `Retry-After` header. If issues persist, implement request throttling in your application.

#### Import Errors
```
Error: ModuleNotFoundError: No module named 'wex_health'
```
**Solution**: Ensure package is installed
```bash
pip install wex-health-sdk
```

### Debug Mode

Enable debug logging to troubleshoot issues:

```python
import logging
logging.basicConfig(level=logging.DEBUG)

# SDK will log detailed request/response information
```

## Getting Started

Please follow the [installation procedure](#installation--usage) and then run the following:

```python

import wex_health
from wex_health.rest import ApiException
from pprint import pprint

# Host URL must be explicitly provided - no default to avoid exposing internal URLs
# See configuration.py for a list of all supported configuration parameters.
configuration = wex_health.Configuration(
    host = os.environ.get('API_HOST', 'https://api.example.com')  # Replace with your API endpoint
)

# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.

# Configure API key authorization: Bearer
configuration.api_key['Bearer'] = os.environ["API_KEY"]

# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['Bearer'] = 'Bearer'


# Enter a context with an instance of the API client
async with wex_health.ApiClient(configuration) as api_client:
    # Create an instance of the API class
    api_instance = wex_health.ClaimsApi(api_client)
    person_id = 'person_id_example' # str | The GUID generated by the Identity Management System for accessing information belonging to this specific person.
    claim_number = 'claim_number_example' # str | The Claim number, an alphanumeric string, e.g. 11BPEB1210513P0000101
    x_request_id = 'x_request_id_example' # str | Optional correlation ID associated with the request, comprised of alphanumeric or hyphen characters up to 36 characters in length. (optional)

    try:
        # Get Claim
        api_response = await api_instance.get_claim(person_id, claim_number, x_request_id=x_request_id)
        print("The response of ClaimsApi->get_claim:\n")
        pprint(api_response)
    except ApiException as e:
        print("Exception when calling ClaimsApi->get_claim: %s\n" % e)

```

## Documentation for API Endpoints

All URIs are relative to the host URL you configure when creating the Configuration object.

Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*ClaimsApi* | [**get_claim**](docs/ClaimsApi.md#get_claim) | **GET** /claims/v1/consumers/{person_id}/claims/{claim_number} | Get Claim
*ClaimsApi* | [**get_claims_for_business**](docs/ClaimsApi.md#get_claims_for_business) | **GET** /claims/v1/businesses/{business_id}/claims | Get Claims for Business
*ClaimsApi* | [**get_claims_for_participant**](docs/ClaimsApi.md#get_claims_for_participant) | **GET** /claims/v1/consumers/{person_id}/claims | Get Claims for Participant
*ClaimsApi* | [**get_payees_for_participant**](docs/ClaimsApi.md#get_payees_for_participant) | **GET** /claims/v1/consumers/{person_id}/payees | Get Payees
*ClaimsApi* | [**get_receipt_for_participant**](docs/ClaimsApi.md#get_receipt_for_participant) | **GET** /claims/v1/consumers/{person_id}/receipts/{receipt_id} | Get Receipt
*ClaimsApi* | [**get_receipts_for_participant**](docs/ClaimsApi.md#get_receipts_for_participant) | **GET** /claims/v1/consumers/{person_id}/receipts | Get Receipts
*HealthApi* | [**get_liveness**](docs/HealthApi.md#get_liveness) | **GET** /claims/health/liveness | Get Liveness


## Documentation For Models

 - [ClaimDTO](docs/ClaimDTO.md)
 - [ClaimsDTO](docs/ClaimsDTO.md)
 - [DenialReasonDTO](docs/DenialReasonDTO.md)
 - [GetLiveness200Response](docs/GetLiveness200Response.md)
 - [GetLiveness503Response](docs/GetLiveness503Response.md)
 - [PayeeDTO](docs/PayeeDTO.md)
 - [PayeesDTO](docs/PayeesDTO.md)
 - [ProblemDetails](docs/ProblemDetails.md)
 - [ReceiptDTO](docs/ReceiptDTO.md)
 - [ReceiptsDTO](docs/ReceiptsDTO.md)
 - [RmiDTO](docs/RmiDTO.md)


<a id="documentation-for-authorization"></a>
## Documentation For Authorization


Authentication schemes defined for the API:
<a id="Bearer"></a>
### Bearer

- **Type**: API key
- **API key parameter name**: Authorization
- **Location**: HTTP header


## License

This software is proprietary and confidential. All rights reserved.

**Copyright (c) 2025 Wex Inc.**

This software and associated documentation files (the "Software") are the proprietary and confidential information of Wex Inc. ("Wex").

### Usage Terms

- **Proprietary License**: This Software is provided under a proprietary license agreement
- **Restricted Use**: The Software is intended for authorized use only
- **No Redistribution**: You may not redistribute, sublicense, or modify the Software without prior written permission from Wex
- **Confidentiality**: All information contained herein is proprietary to Wex and protected by trade secret, copyright, and patent law
- **No Warranty**: The Software is provided "AS IS" without warranty of any kind

### Licensing Inquiries

For licensing inquiries or questions about usage rights, please contact:

- **Email**: support@wexinc.com
- **Organization**: Wex Inc.

See the [LICENSE](LICENSE) file for full license terms.

## Author

support@wexinc.com


## Documentation For Authorization

Authentication schemes defined for the API:
### bearerAuth

- **Type**: Bearer authentication (JWT)

### OAuth2 Client Credentials

- **Type**: OAuth2 Client Credentials Grant
- **Flow**: Client credentials are sent in request body using `application/x-www-form-urlencoded`
- **Token URL**: Must be configured via `access_token_url` parameter (e.g., `https://api.example.com/oauth/token`)

For detailed OAuth2 setup and usage examples, see [OAuth2 Authentication Guide](docs/OAUTH2_GUIDE.md).

