Metadata-Version: 2.4
Name: axedz
Version: 1.0.0
Summary: Production-grade Python SDK for the AxeDz CPaaS API (SMS, Email, Wallet)
Project-URL: Homepage, https://github.com/axedz/axedz-python
Project-URL: Documentation, https://github.com/axedz/axedz-python#readme
Project-URL: Repository, https://github.com/axedz/axedz-python
Project-URL: Issues, https://github.com/axedz/axedz-python/issues
Author: AxeDz Team
License-Expression: MIT
License-File: LICENSE
Keywords: api,axedz,billing,communications,cpaas,email,sdk,sms,wallet
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT 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 :: Communications
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: requests>=2.28.0
Provides-Extra: async
Requires-Dist: httpx>=0.27.0; extra == 'async'
Provides-Extra: dev
Requires-Dist: httpx>=0.27.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.12; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: responses>=0.25.0; extra == 'dev'
Description-Content-Type: text/markdown

# AxeDz Python SDK

Production-grade Python SDK for the [AxeDz CPaaS](https://axedz.com) platform. Send SMS and email, manage wallet balances, and inspect usage transactions with a clean, typed API inspired by Stripe and Twilio SDKs.

## Features

- SMS and email sending
- Wallet balance and transaction history
- API key authentication via `x-api-key` header
- Automatic retries with exponential backoff (network and 5xx errors)
- Rich, typed exception hierarchy
- Standardized response envelope (`success`, `data`, `meta`)
- Optional async client via `httpx`
- Environment variable configuration

## Installation

```bash
pip install axedz
```

For async support:

```bash
pip install axedz[async]
```

## Authentication

All requests are authenticated with your AxeDz API key via the `x-api-key` header:

```
x-api-key: <API_KEY>
```

You can pass the key directly or via environment variable:

```bash
export AXEDZ_API_KEY="your_api_key"
export AXEDZ_BASE_URL="https://your-api.example.com/api"  # optional
```

## Quick Start

```python
from axedz import AxeDz

client = AxeDz("API_KEY")

# Send SMS
client.sms.send("+213xxxxxxxx", "Hello")

# Send email
client.email.send(
    "user@mail.com",
    "Welcome",
    text="Hello from AxeDz",
)

# Wallet balance
print(client.wallet.balance())

# Usage transactions
print(client.wallet.transactions(limit=20, offset=0))
```

## Usage

### Initialize the client

```python
from axedz import AxeDz

client = AxeDz(
    api_key="your_api_key",
    base_url="http://localhost:3000/api",  # default
    timeout=10,                             # seconds
    max_retries=2,                          # retry network/5xx failures
    debug=False,                            # enable request logging
)
```

Or use environment variables:

```python
client = AxeDz()  # reads AXEDZ_API_KEY and AXEDZ_BASE_URL
```

Use as a context manager to ensure the HTTP session is closed:

```python
with AxeDz("API_KEY") as client:
    client.sms.send("+213555123456", "Hello")
```

### SMS

```python
response = client.sms.send(
    to="+213555123456",
    message="Your verification code is 123456",
)

print(response["success"])  # True
print(response["data"])     # {"id": "...", "status": "queued"}
print(response["meta"])     # {"status_code": 202, ...}
```

Optional provider override:

```python
client.sms.send("+213555123456", "Hello", provider="twilio")
```

### Email

Send plain text:

```python
client.email.send(
    "user@example.com",
    "Welcome to AxeDz",
    text="Thanks for signing up!",
)
```

Send HTML:

```python
client.email.send(
    "user@example.com",
    "Invoice",
    html="<h1>Your invoice</h1><p>Thank you.</p>",
)
```

### Wallet

Fetch balance:

```python
balance = client.wallet.balance()
print(balance["data"]["balance"])
print(balance["data"]["currency"])
```

List usage transactions:

```python
transactions = client.wallet.transactions(limit=20, offset=0)

for event in transactions["data"]["records"]:
    print(event)

pagination = transactions["data"]["pagination"]
print(pagination["total"], pagination["hasMore"])
```

## Response format

Every SDK method returns a normalized envelope:

```python
{
    "success": True,
    "data": { ... },   # API payload
    "meta": { ... },   # status code, headers, pagination, etc.
}
```

Raw HTTP responses are never exposed.

## Error handling

The SDK raises typed exceptions with full context:

| Exception             | When                                      |
|-----------------------|-------------------------------------------|
| `ValidationError`     | Invalid input or 400/422 API responses    |
| `AuthenticationError` | Missing/invalid API key (401/403)         |
| `RateLimitError`      | Rate limit exceeded (429)                 |
| `ServerError`         | Server-side failures (5xx)                |
| `NetworkError`        | Timeouts and connectivity issues          |
| `AxeDzError`          | Base class for all SDK errors             |

Example:

```python
from axedz import AxeDz, AuthenticationError, ValidationError

client = AxeDz("API_KEY")

try:
    client.sms.send("", "Hello")
except ValidationError as error:
    print(error.message)
    print(error.status_code)
    print(error.response_body)
    print(error.request)
except AuthenticationError as error:
    print("Check your API key:", error.message)
```

## Retries

The SDK automatically retries failed requests when:

- A network error occurs (timeout, connection failure)
- The API returns a 5xx server error

It does **not** retry validation, authentication, or rate-limit errors. Retries use exponential backoff (default: 2 attempts).

## Async client (optional)

```python
import asyncio
from axedz.async_client import AsyncAxeDz

async def main():
    async with AsyncAxeDz("API_KEY") as client:
        result = await client.sms.send("+213555123456", "Hello")
        print(result)

asyncio.run(main())
```

Install async dependencies first:

```bash
pip install axedz[async]
```

## Development

```bash
git clone https://github.com/axedz/axedz-python.git
cd axedz-python
pip install -e ".[dev]"
pytest
```

## License

MIT — see [LICENSE](LICENSE).
