Metadata-Version: 2.4
Name: dlt-unirate
Version: 0.1.0
Summary: dlt (dltHub) source for the UniRate currency-exchange API — load live exchange rates, supported currencies, and VAT rates into any dlt destination.
Project-URL: Homepage, https://github.com/UniRate-API/dlt-unirate
Project-URL: Repository, https://github.com/UniRate-API/dlt-unirate
Project-URL: Issues, https://github.com/UniRate-API/dlt-unirate/issues
Project-URL: Provider, https://unirateapi.com
Author: Unirate Team
License: MIT
License-File: LICENSE
Keywords: currency,dlt,etl,exchange-rates,fintech,forex,unirate,vat
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 :: Database
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Requires-Dist: dlt<2.0,>=1.0.0
Requires-Dist: requests<3.0,>=2.31
Description-Content-Type: text/markdown

# dlt-unirate

[![PyPI](https://img.shields.io/pypi/v/dlt-unirate.svg)](https://pypi.org/project/dlt-unirate/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A [dlt](https://dlthub.com) source for the [UniRate API](https://unirateapi.com)
— load live currency exchange rates, the supported-currency list, and
per-country VAT rates into any dlt destination (DuckDB, BigQuery, Snowflake,
Postgres, filesystem, …).

UniRate provides 593+ fiat, crypto, and commodity exchange rates. Latest rates,
currencies, and VAT rates are available on the free tier; historical rates
require a Pro plan.

## Why this package

dlt has no built-in FX source, so people hand-roll a `requests` loop or a
`rest_api` config every time they need exchange rates in a warehouse. This
package gives you a typed, tested `@dlt.source` with three resources you can
drop straight into a pipeline.

## Install

```bash
pip install dlt-unirate
```

This pulls in `dlt` and `requests`. Add a destination extra for your target,
e.g. `pip install "dlt[duckdb]"`.

## Quick start

```python
import dlt
from dlt_unirate import unirate_source

pipeline = dlt.pipeline(
    pipeline_name="unirate",
    destination="duckdb",
    dataset_name="unirate_data",
)

# api_key resolves from dlt secrets / the UNIRATE_API_KEY env var,
# or pass it explicitly: unirate_source(api_key="...").
load_info = pipeline.run(unirate_source(base_currency="USD"))
print(load_info)
```

That loads three tables: `exchange_rates`, `currencies`, and `vat_rates`.

## Configuring the API key

`unirate_source` follows dlt's config/secrets convention. Any of these work:

- **Env var:** `export UNIRATE_API_KEY="..."`
- **dlt secrets** — `.dlt/secrets.toml`:

  ```toml
  [sources.unirate]
  api_key = "..."
  ```
- **Explicit argument:** `unirate_source(api_key="...")`

Get a free key at [unirateapi.com](https://unirateapi.com).

## Resources

| Resource | Table columns | Notes |
|---|---|---|
| `exchange_rates` | `base_currency`, `target_currency`, `rate` | Every current rate for `base_currency`. `write_disposition="replace"`. |
| `currencies` | `currency_code` | All supported currency codes. `replace`. |
| `vat_rates` | `country_code`, `country_name`, `vat_rate` | Per-country VAT rates. `replace`. |
| `historical_exchange_rates` | `date`, `base_currency`, `target_currency`, `rate` | **Pro-gated** — off by default. `merge` on `(date, base, target)`. |

## Source parameters

| Parameter | Default | Description |
|---|---|---|
| `api_key` | dlt secret / `UNIRATE_API_KEY` | UniRate API key. |
| `base_currency` | `"USD"` | Base for `exchange_rates` (and historical). |
| `base_url` | `https://api.unirateapi.com` | API base URL. |
| `request_timeout` | `30` | Per-request timeout, seconds. |
| `include_historical` | `False` | Also yield the Pro-gated historical resource. |
| `historical_dates` | `None` | `YYYY-MM-DD` dates to pull historical rates for. |

### Historical rates (Pro)

```python
source = unirate_source(
    base_currency="EUR",
    include_historical=True,
    historical_dates=["2024-01-01", "2024-02-01"],
)
pipeline.run(source)
```

Historical endpoints return HTTP 403 on the free tier (surfaced as
`ProSubscriptionError`); a UniRate Pro plan is required.

## Selecting a subset of resources

```python
# Only load exchange rates and currencies.
pipeline.run(unirate_source().with_resources("exchange_rates", "currencies"))
```

## Error handling

Errors raised by the underlying client all inherit from `UniRateError`:

| HTTP | Exception |
|---|---|
| 401 | `AuthenticationError` |
| 403 | `ProSubscriptionError` |
| 404 | `InvalidCurrencyError` |
| 429 | `RateLimitError` |
| other non-2xx | `APIError` (carries `status_code`) |
| network / transport | `UniRateError` |

## Related UniRate clients

If you want to call the API directly, there are official clients in
[Python](https://github.com/UniRate-API/unirate-api-python),
[Node.js](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), and
[Swift](https://github.com/UniRate-API/unirate-api-swift), plus data-stack
integrations for [dbt](https://github.com/UniRate-API/dbt-unirate),
[Airflow](https://github.com/UniRate-API/airflow-provider-unirate), and
[LangChain](https://github.com/UniRate-API/langchain-unirate).

## License

MIT — see [LICENSE](LICENSE).
