unirate-api 0.1.0

Official Rust client for the UniRate API — free currency exchange rates, historical data, and VAT rates.
Documentation
# UniRate Rust Client

Official Rust client for the [UniRate API](https://unirateapi.com) — free, real-time and historical currency exchange rates plus VAT rates.

- Real-time exchange rates between 170+ currencies (fiat + crypto)
- Historical rates back to 1999
- Time-series ranges up to 5 years
- Currency conversion (current and historical)
- VAT rates for countries worldwide
- Free tier, no credit card required
- Modern Rust: `async`/`await`, `Send + Sync`, `serde`-derived models
- Pulls in only `reqwest` (rustls) + `serde` + `thiserror` — no OpenSSL dependency

## Requirements

- Rust 1.74+ (stable)
- An async runtime (examples and tests use [`tokio`])

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
unirate-api = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```

Or via the CLI:

```bash
cargo add unirate-api
```

## Quick start

```rust
use unirate_api::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("your-api-key");

    // Current rate
    let rate = client.get_rate("USD", "EUR").await?;
    println!("USD -> EUR: {rate}");

    // Convert
    let euros = client.convert(100.0, "USD", "EUR").await?;
    println!("100 USD = {euros} EUR");

    // All supported currencies
    let currencies = client.get_supported_currencies().await?;
    println!("{} currencies supported", currencies.len());
    Ok(())
}
```

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

## API

### Current rates

```rust
// Single pair
let rate: f64 = client.get_rate("USD", "EUR").await?;

// All rates for a base
let rates: std::collections::HashMap<String, f64> =
    client.get_all_rates("USD").await?;

// Convert an amount
let result: f64 = client.convert(100.0, "USD", "EUR").await?;

// Supported currency list
let codes: Vec<String> = client.get_supported_currencies().await?;
```

### Historical data (Pro)

These endpoints return `403` on the free tier and surface as
`UniRateError::Api { status: 403, .. }`.

```rust
// Rate on a specific date
let rate = client.get_historical_rate("2024-01-01", "USD", "EUR").await?;

// All rates on a date
let rates = client.get_historical_rates("2024-01-01", "USD").await?;

// Convert using historical rate
let amount = client
    .convert_historical(100.0, "USD", "EUR", "2024-01-01")
    .await?;

// Time series
let series = client
    .get_time_series(
        "2024-01-01",
        "2024-01-07",
        "USD",
        Some(&["EUR", "GBP"]),
        1.0,
    )
    .await?;

// Available historical coverage per currency
let limits = client.get_historical_limits().await?;
```

### VAT rates

```rust
// All countries
let vat = client.get_vat_rates().await?;

// Single country (ISO-3166 alpha-2)
let germany = client.get_vat_rate("DE").await?;
println!("Germany VAT: {}%", germany.vat_data.vat_rate);
```

## Error handling

All methods return `Result<T, UniRateError>`:

```rust
use unirate_api::UniRateError;

match client.get_rate("USD", "ZZZ").await {
    Ok(rate) => println!("{rate}"),
    Err(UniRateError::Authentication) => eprintln!("bad api key"),
    Err(UniRateError::InvalidCurrency) => eprintln!("unknown currency code"),
    Err(UniRateError::RateLimit) => eprintln!("back off and retry"),
    Err(UniRateError::InvalidDate) => eprintln!("bad date format"),
    Err(UniRateError::Api { status, body }) => eprintln!("HTTP {status}: {body}"),
    Err(e) => eprintln!("transport error: {e}"),
}
```

## Advanced — custom `reqwest::Client`

Use `Client::builder` to swap in a pre-configured HTTP client — handy for
tests against a local `wiremock::MockServer`, or to share a connection pool
with the rest of your app:

```rust
use std::time::Duration;
use unirate_api::Client;

let http = reqwest::Client::builder()
    .timeout(Duration::from_secs(10))
    .build()?;

let client = Client::builder("your-api-key")
    .http_client(http)
    .build()?;
```

## Rate limits

- **Currency endpoints:** standard rate limits apply
- **Historical endpoints:** 50 requests/hour on the free tier
- **VAT endpoints:** 1800 requests/hour on the free tier

## Related clients

- [unirate-api-python](https://github.com/UniRate-API/unirate-api-python) (PyPI: `unirate-api`)
- [unirate-api-nodejs](https://github.com/UniRate-API/unirate-api-nodejs) (npm: `unirate-api`)
- [unirate-api-swift](https://github.com/UniRate-API/unirate-api-swift) (Swift Package Manager)

<!-- 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:** [NestJS](https://github.com/UniRate-API/nestjs-unirate) · [Django / Wagtail](https://github.com/UniRate-API/wagtail-unirate) · [FastAPI](https://github.com/UniRate-API/fastapi-unirate) · [Flask](https://github.com/UniRate-API/flask-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)
- **Editors / tools:** [VS Code](https://github.com/UniRate-API/vscode-unirate) · [Obsidian](https://github.com/UniRate-API/obsidian-currency)
- **Specialty bridges:** [NodaMoney (.NET)](https://github.com/UniRate-API/UniRateApi.NodaMoney)

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

## License

MIT — see [LICENSE](LICENSE).