Skip to main content

FastAPI integration for the UniRate currency-exchange API — async dependency, lifespan manager, Money Pydantic type, and response-conversion middleware.

Project description

fastapi-unirate

PyPI Python License

FastAPI integration for the UniRate currency-exchange API:

  • Async dependencyDepends(get_unirate_client) plus a typed UniRateDep alias for path-operation signatures.
  • Lifespan helper — one shared httpx.AsyncClient-backed UniRate client per app, opened on startup and closed on shutdown.
  • Money Pydantic type — amount + currency pair that round-trips through OpenAPI schemas.
  • CurrencyConversionMiddleware — auto-rewrites Money-shaped values in JSON responses to a request-scoped target currency (?currency=EUR).

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

Install

pip install fastapi-unirate

Or with uv / Poetry:

uv add fastapi-unirate
poetry add fastapi-unirate

Quick start

import os

from fastapi import FastAPI
from fastapi_unirate import (
    CurrencyConversionMiddleware,
    Money,
    UniRateDep,
    unirate_lifespan,
)

app = FastAPI(lifespan=unirate_lifespan())  # reads UNIRATE_API_KEY from env
app.add_middleware(CurrencyConversionMiddleware)


@app.get("/products/widget")
async def get_widget() -> dict[str, Money]:
    return {"price": Money(amount=19.99, currency="USD")}


@app.get("/rate/{base}/{quote}")
async def rate(base: str, quote: str, client: UniRateDep) -> dict[str, float]:
    return {"rate": await client.get_rate(base, quote)}

Then:

$ curl localhost:8000/products/widget
{"price":{"amount":19.99,"currency":"USD"}}

$ curl localhost:8000/products/widget?currency=EUR
{"price":{"amount":18.42,"currency":"EUR"}}

$ curl localhost:8000/rate/USD/JPY
{"rate":151.83}

The middleware finds every {"amount": <number>, "currency": "<code>"} shape — top-level, nested, or inside lists — and rewrites it. Conversions are de-duplicated per request and run concurrently.

Configuration

unirate_lifespan accepts overrides:

app = FastAPI(
    lifespan=unirate_lifespan(
        api_key="...",                         # default: $UNIRATE_API_KEY
        base_url="https://api.unirateapi.com", # default: production
        timeout=15.0,                          # default: 30s
    )
)

CurrencyConversionMiddleware accepts the query-parameter name and an explicit client (mostly for testing):

app.add_middleware(
    CurrencyConversionMiddleware,
    query_param="display_currency",
)

Why a middleware?

The dossier sketched two integration shapes — DI and middleware — and both pull their weight:

  • The DI provider is the right tool when a handler explicitly wants to call convert() or get_rate().
  • The middleware is the right tool when a service has a stable Money-shaped response and wants to expose one ?currency= knob to clients without rewriting every handler.

You can use either, or both together (as in the quick-start example).

Errors

The client raises UniRateAPIError on non-2xx responses (with status_code set). Common cases:

HTTP Meaning
401 Missing or invalid API key
403 Pro subscription required (historical, commodities)
404 Currency not found
429 Rate limit exceeded

The middleware swallows UniRateAPIError and passes the original response through unchanged — so an upstream UniRate outage never becomes a 500 on your service.

Compatibility

  • Python 3.9 – 3.13
  • FastAPI ≥ 0.100
  • Pydantic ≥ 2.0

Related

  • unirate-api — sync UniRate Python client (this package vendors a small async equivalent so it doesn't pull in requests).
  • langchain-unirate — LangChain partner package.
  • Other UniRate integrations: dbt, Airflow, n8n, Raycast, MCP server. Full list at https://unirateapi.com.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_unirate-0.1.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_unirate-0.1.0-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_unirate-0.1.0.tar.gz.

File metadata

  • Download URL: fastapi_unirate-0.1.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastapi_unirate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 55de2a8b8f53f565f8ecad5d83318aa47cc9f89e825f285aa3eab9866e87a183
MD5 2d6c616ad6919f63894be521714f27ae
BLAKE2b-256 dfe61200e1fbac4ecafa11a8e0b9e40123dfd65a1e492d22dd181153252cf392

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_unirate-0.1.0.tar.gz:

Publisher: release.yml on UniRate-API/fastapi-unirate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastapi_unirate-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_unirate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 42b7bc355a22c605fcca9a39e515e997cf1233fe7cc632c7df44659260b0ec24
MD5 7852247a755fd18db57d4ceb43a03c65
BLAKE2b-256 d0bf480eafd70d81859bff1b2f938ae08ecb95ebd83d7709dc7027b10622e751

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_unirate-0.1.0-py3-none-any.whl:

Publisher: release.yml on UniRate-API/fastapi-unirate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page