Metadata-Version: 2.5
Name: litestar-unirate
Version: 0.1.0
Summary: Litestar plugin for the UniRate currency-exchange API — an async dependency-injected client plus prebuilt rate/convert/currencies/VAT route handlers.
Project-URL: Homepage, https://github.com/UniRate-API/litestar-unirate
Project-URL: Repository, https://github.com/UniRate-API/litestar-unirate
Project-URL: Issues, https://github.com/UniRate-API/litestar-unirate/issues
Project-URL: Provider, https://unirateapi.com
Author: Unirate Team
License: MIT
License-File: LICENSE
Keywords: currency,exchange-rates,fintech,litestar,unirate
Classifier: Development Status :: 4 - Beta
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.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: litestar<3.0,>=2.0.0
Description-Content-Type: text/markdown

# litestar-unirate

[![PyPI](https://img.shields.io/pypi/v/litestar-unirate.svg)](https://pypi.org/project/litestar-unirate/)
[![Python](https://img.shields.io/pypi/pyversions/litestar-unirate.svg)](https://pypi.org/project/litestar-unirate/)
[![License](https://img.shields.io/pypi/l/litestar-unirate.svg)](https://github.com/UniRate-API/litestar-unirate/blob/main/LICENSE)

[Litestar](https://litestar.dev) plugin for the [UniRate](https://unirateapi.com)
currency-exchange API:

- **`UniRatePlugin`** — an `InitPluginProtocol` plugin that provides a shared,
  async `UniRateClient` to your handlers through Litestar's dependency
  injection (injected as `unirate` by default).
- **Prebuilt route handlers** — a `UniRateController` mounted at `/unirate`
  exposing `GET /unirate/rate`, `/convert`, `/currencies`, and `/vat`, with
  full UniRate error mapping onto Litestar HTTP exceptions.
- **One HTTP client per app** — an `httpx.AsyncClient`-backed client opened on
  demand and closed on shutdown.

UniRate covers 593+ fiat, crypto, and commodity codes. Latest rates,
conversion, currencies, and VAT are on the free tier; historical endpoints
(`convert_historical`) require Pro.

## Install

```bash
pip install litestar-unirate
```

Or with uv / Poetry:

```bash
uv add litestar-unirate
poetry add litestar-unirate
```

## Quick start

```python
from litestar import Litestar, get

from litestar_unirate import UniRateClient, UniRateConfig, UniRatePlugin

app = Litestar(
    plugins=[UniRatePlugin(UniRateConfig())],  # reads UNIRATE_API_KEY from env
)
```

That alone mounts the prebuilt endpoints:

```
$ curl 'localhost:8000/unirate/rate?from_currency=USD&to_currency=JPY'
{"rate":151.83}

$ curl 'localhost:8000/unirate/convert?from_currency=USD&to_currency=EUR&amount=100'
{"result":92.5}

$ curl localhost:8000/unirate/currencies
{"currencies":["USD","EUR","GBP", ...]}

$ curl 'localhost:8000/unirate/vat?country=DE'
{"country":"DE","vat_data":{"country_code":"DE","country_name":"Germany","vat_rate":19.0}}
```

The plugin also injects the client into your own handlers under the `unirate`
key:

```python
@get("/summary")
async def summary(unirate: UniRateClient) -> dict[str, object]:
    return {"usd_eur": await unirate.get_rate("USD", "EUR")}
```

## Configuration

`UniRateConfig` controls the client and the routes:

```python
UniRateConfig(
    api_key=None,                          # default: $UNIRATE_API_KEY
    base_url="https://api.unirateapi.com", # default: production
    timeout=30.0,                          # HTTP timeout (seconds)
    dependency_key="unirate",              # DI name for the client
    register_routes=True,                  # mount the prebuilt /unirate/* routes
    route_path_prefix="/unirate",          # where to mount them
)
```

Set `register_routes=False` to expose only the injectable client and wire your
own handlers.

> **Note:** the prebuilt `UniRateController` injects the client under the name
> `unirate`. If you set a custom `dependency_key`, keep `register_routes=False`
> (or use the default key) so the controller resolves its dependency.

## Client methods

The injected `UniRateClient` is a small async wrapper over UniRate:

| Method | Returns |
|--------|---------|
| `get_rate(from_currency="USD", to_currency=None)` | `float` for a pair, else `dict[str, float]` |
| `convert(from_currency, to_currency, amount=1.0)` | `float` |
| `get_supported_currencies()` | `list[str]` |
| `get_vat_rates(country=None)` | `dict` (`vat_rates` map, or `vat_data` for one country) |
| `convert_historical(from_currency, to_currency, date, amount=1.0)` | `float` (Pro) |

## Errors

The client raises `UniRateAPIError` (with `status_code`) on non-2xx responses.
The prebuilt handlers translate those onto Litestar HTTP exceptions:

| UniRate HTTP | Litestar exception | Response |
|------|-----------------------------|------|
| 400  | `ClientException`           | 400 |
| 401  | `NotAuthorizedException`    | 401 |
| 403  | `PermissionDeniedException` | 403 (Pro required) |
| 404  | `NotFoundException`         | 404 |
| 429  | `TooManyRequestsException`  | 429 |
| 503  | `ServiceUnavailableException` | 503 |
| transport / other | `HTTPException` | 502 |

## Compatibility

- Python 3.10 – 3.13
- Litestar ≥ 2.0
- httpx ≥ 0.27

## Related

- [`unirate-api`](https://pypi.org/project/unirate-api/) — sync UniRate Python
  client.
- [`fastapi-unirate`](https://pypi.org/project/fastapi-unirate/) — FastAPI
  integration.
- [`flask-unirate`](https://pypi.org/project/flask-unirate/) — Flask
  integration.
- Other UniRate integrations: dbt, Airflow, LangChain, MCP server. Full list at
  <https://unirateapi.com>.

<!-- unirate-ecosystem-footer:start -->
## Other UniRate clients

UniRate ships official client libraries and framework integrations across the
ecosystem. The repos below are all maintained under the
[UniRate-API](https://github.com/UniRate-API) org.

- **Languages:** [Python](https://github.com/UniRate-API/unirate-api-python) · [Node.js / TypeScript](https://github.com/UniRate-API/unirate-api-nodejs) · [Go](https://github.com/UniRate-API/unirate-api-go) · [Rust](https://github.com/UniRate-API/unirate-api-rust) · [Java](https://github.com/UniRate-API/unirate-api-java) · [Ruby](https://github.com/UniRate-API/unirate-api-ruby) · [PHP](https://github.com/UniRate-API/unirate-api-php) · [.NET](https://github.com/UniRate-API/unirate-api-dotnet) · [Swift](https://github.com/UniRate-API/unirate-api-swift)
- **Web frameworks:** [FastAPI](https://github.com/UniRate-API/fastapi-unirate) · [Flask](https://github.com/UniRate-API/flask-unirate) · [NestJS](https://github.com/UniRate-API/nestjs-unirate) · [Django / Wagtail](https://github.com/UniRate-API/wagtail-unirate) · [React](https://github.com/UniRate-API/react-unirate) · [tRPC](https://github.com/UniRate-API/trpc-unirate)
- **Static-site generators:** [Astro](https://github.com/UniRate-API/astro-unirate) · [Eleventy](https://github.com/UniRate-API/eleventy-unirate) · [Hugo](https://github.com/UniRate-API/hugo-unirate)
- **Data / orchestration:** [Airflow](https://github.com/UniRate-API/airflow-provider-unirate) · [dbt](https://github.com/UniRate-API/dbt-unirate) · [LangChain](https://github.com/UniRate-API/langchain-unirate)
- **Workflow / no-code:** [n8n](https://github.com/UniRate-API/n8n-nodes-unirate) · [Google Sheets](https://github.com/UniRate-API/unirate-sheets) · [MCP server](https://github.com/UniRate-API/unirate-mcp)

Get a free API key at [unirateapi.com](https://unirateapi.com).
<!-- unirate-ecosystem-footer:end -->

## License

MIT
