Metadata-Version: 2.4
Name: modelpricing-ai
Version: 2026.2.8
Summary: Python client for ModelPricing.ai cost estimates
Project-URL: Homepage, https://modelpricing.ai
Author: ModelPricing.ai
License: MIT
License-File: LICENSE
Keywords: ai,anthropic,cost,estimate,llm,model,openai,pricing,token,usage
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
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 :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: pydantic>=2.3.0
Requires-Dist: requests>=2.31.0
Requires-Dist: tenacity>=8.0.0
Provides-Extra: dev
Requires-Dist: build>=1.2.1; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# modelpricing-ai

Python client for the [ModelPricing.ai](https://modelpricing.ai) API — estimate LLM usage costs with a single call.

## Installation

```bash
pip install modelpricing-ai
```

## Quick Start

```python
from modelpricing_ai import ModelPricingClient

client = ModelPricingClient(api_key="YOUR_API_KEY")

estimate = client.estimate(
    model="gpt-4o-mini",
    tokens_in=1000,
    tokens_out=500,
    trace_id={"requestId": "abc-123"},
)
print(f"Cost: ${estimate.total:.6f}")
```

## Async Usage

```python
import asyncio
from modelpricing_ai import AsyncModelPricingClient

async def main():
    client = AsyncModelPricingClient(api_key="YOUR_API_KEY")
    estimate = await client.estimate(
        model="gpt-4o-mini",
        tokens_in=1000,
        tokens_out=500,
        trace_id={"requestId": "abc-123"},
    )
    print(f"Cost: ${estimate.total:.6f}")

asyncio.run(main())
```

## Response Structure

Both `estimate()` and `await estimate()` return an `EstimateResponse` object:

```python
estimate.total        # float — total USD cost
estimate.model        # str   — canonical model name
estimate.traceId      # dict | None — your pass-through trace ID
estimate.breakdown    # EstimateBreakdownGroup
  .input              # EstimateBreakdown
    .unit             #   str   — e.g. "token"
    .branch           #   str   — pricing tier that matched
    .qty              #   int   — number of input tokens
    .rate             #   float — per-unit rate
    .subtotal         #   float — input cost
  .output             # EstimateBreakdown (same fields for output tokens)
```

## Configuration

| Parameter     | Default                         | Description                                                              |
| ------------- | ------------------------------- | ------------------------------------------------------------------------ |
| `api_key`     | _required_                      | Your ModelPricing.ai API key (also reads `MODELPRICING_API_KEY` env var) |
| `base_url`    | `"https://api.modelpricing.ai"` | API base URL (also reads `MODELPRICING_BASE_URL` env var)                |
| `timeout`     | `30.0`                          | Request timeout in seconds                                               |
| `max_retries` | `3`                             | Maximum retry attempts for transient errors                              |
| `session`     | `None`                          | Optional `requests.Session` (sync) or `aiohttp.ClientSession` (async)    |

```python
client = ModelPricingClient(
    api_key="YOUR_API_KEY",
    base_url="https://api.modelpricing.ai",
    timeout=30.0,
    max_retries=3,
)
```

## Error Handling

The client raises typed exceptions for different failure modes:

| Exception         | HTTP Status | When                          |
| ----------------- | ----------- | ----------------------------- |
| `Unauthorized`    | 401         | Invalid or missing API key    |
| `ValidationError` | 422         | Invalid model name or metrics |
| `NotFound`        | 404         | Unknown endpoint              |
| `ServerError`     | 5xx         | Server-side failures          |

All exceptions inherit from `ModelPricingError` and include a `status_code` attribute.

```python
from modelpricing_ai.errors import Unauthorized, ValidationError, ServerError

try:
    estimate = client.estimate(model="gpt-4o-mini", tokens_in=1000, tokens_out=500)
except Unauthorized:
    print("Check your API key")
except ValidationError as e:
    print(f"Bad request: {e}")
except ServerError:
    print("Server error — will be retried automatically")
```

## Retry Behavior

The client automatically retries on transient errors with exponential backoff:

- **Retries**: 5xx server errors and network/connection errors
- **No retry**: 4xx client errors (401, 404, 422)
- **Default**: 3 retries with exponential backoff (1 s, 2 s, 4 s up to 10 s max)

```python
# Increase retries for unreliable networks
client = ModelPricingClient(api_key="YOUR_API_KEY", max_retries=5)

# Disable retries (no retry attempts)
client = ModelPricingClient(api_key="YOUR_API_KEY", max_retries=0)
```

## License

MIT
