Flask extension for the UniRate currency-exchange API — Jinja filters, optional Flask-Caching integration, and current_app.unirate access.
Project description
flask-unirate
Flask extension for the UniRate currency-exchange API:
- Drop-in
UniRate(app)extension — follows the standardinit_appfactory pattern, registers itself onapp.extensions["unirate"]. - Jinja filters —
{{ amount|to_currency('EUR') }},{{ amount|convert_currency('USD', 'JPY') }},{{ price|format_money('USD') }}, plusto_usd/to_eur/to_gbpshortcuts. - Optional Flask-Caching integration — set
UNIRATE_CACHE_TIMEOUTand the extension caches latest-rate / supported-currency lookups through whatever Flask-Caching backend you already have. - Wraps the official
unirate-apiPython client; full method surface is reachable throughunirate.clientif you need historical rates / VAT / time series.
UniRate covers 593+ fiat, crypto, and commodity codes. Latest rates and
conversion are on the free tier; historical endpoints
(get_historical_rate, convert_historical) require Pro.
Install
pip install flask-unirate
With Flask-Caching support:
pip install "flask-unirate[caching]"
Quick start
import os
from flask import Flask, render_template_string
from flask_unirate import UniRate
app = Flask(__name__)
app.config["UNIRATE_API_KEY"] = os.environ["UNIRATE_API_KEY"]
unirate = UniRate(app)
@app.route("/rate/<base>/<quote>")
def rate(base: str, quote: str):
return {"rate": unirate.get_rate(base, quote)}
@app.route("/checkout/<int:amount_usd>")
def checkout(amount_usd: int):
return render_template_string(
"""
<p>USD: {{ amount|format_money('USD') }}</p>
<p>EUR: {{ amount|to_eur|format_money('EUR') }}</p>
<p>JPY: {{ amount|to_currency('JPY')|format_money('JPY', decimals=0) }}</p>
""",
amount=amount_usd,
)
Configuration
| Key | Default | Notes |
|---|---|---|
UNIRATE_API_KEY |
— | Required. Falls back to the UNIRATE_API_KEY env var. |
UNIRATE_TIMEOUT |
30 (s) | HTTP timeout passed to UnirateClient. |
UNIRATE_BASE_URL |
https://api.unirateapi.com |
Override only if you proxy the API. |
UNIRATE_DEFAULT_BASE_CURRENCY |
USD |
Default base for the to_currency Jinja filter. |
UNIRATE_CACHE_TIMEOUT |
unset | If set and Flask-Caching is initialised on the app, latest-rate / supported-currency lookups are cached for this many seconds. |
Factory pattern
from flask import Flask
from flask_unirate import UniRate
unirate = UniRate()
def create_app() -> Flask:
app = Flask(__name__)
app.config.from_pyfile("config.py")
unirate.init_app(app)
return app
Inside any view (or template) you can also reach the extension through
current_app:
from flask import current_app
current_app.extensions["unirate"].get_rate("USD", "EUR")
…or through the convenience helper:
from flask_unirate import get_unirate
get_unirate().get_rate("USD", "EUR")
Jinja filters
Every filter is registered automatically when you call UniRate(app) /
init_app(app):
| Filter | Example | Result |
|---|---|---|
to_currency(target, base=None) |
`{{ 100 | to_currency('EUR') }}` |
convert_currency(base, target) |
`{{ 100 | convert_currency('USD', 'JPY') }}` |
format_money(currency, decimals=2) |
`{{ 1234.5 | format_money('USD') }}` |
to_usd / to_eur / to_gbp |
`{{ 100 | to_eur }}` |
Chain them: {{ amount|to_eur|format_money('EUR') }}.
Flask-Caching integration
from flask import Flask
from flask_caching import Cache
from flask_unirate import UniRate
app = Flask(__name__)
app.config.update(
UNIRATE_API_KEY="...",
UNIRATE_CACHE_TIMEOUT=300, # 5 minutes
CACHE_TYPE="RedisCache",
CACHE_REDIS_URL="redis://localhost",
)
Cache(app)
UniRate(app)
The extension auto-discovers the Cache instance off app.extensions['cache']
— so all of Flask-Caching's backends (SimpleCache, RedisCache, MemcachedCache,
FileSystemCache, …) work with no extra wiring. Failures fall through to a
fresh API call rather than raising.
Errors
Errors come from the underlying unirate-api client and propagate
unchanged:
| HTTP | Exception class | Meaning |
|---|---|---|
| 401 | unirate.exceptions.AuthenticationError |
Missing or invalid API key |
| 404 | unirate.exceptions.InvalidCurrencyError |
Currency not found |
| 429 | unirate.exceptions.RateLimitError |
Rate limit exceeded |
| 503 | unirate.exceptions.APIError |
Service unavailable |
| 403 | (raised as requests.HTTPError by raise_for_status) |
Pro plan required (historical, commodities) |
Wrap the call site in try / except UnirateError to catch the whole
family.
Compatibility
- Python 3.9 – 3.13
- Flask ≥ 2.0
unirate-api≥ 1.0- (Optional)
flask-caching≥ 2.0
Related
unirate-api— base sync Python client (this package wraps it).fastapi-unirate— async sibling for FastAPI.langchain-unirate— LangChain partner package.- Other UniRate integrations: dbt, Airflow, n8n, Raycast, MCP server. Full list at https://unirateapi.com.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flask_unirate-0.1.0.tar.gz.
File metadata
- Download URL: flask_unirate-0.1.0.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea085b4dd6e0a2b7b0b1a6891d9d00a82851de032c7b46524e5cb9c985a7eed7
|
|
| MD5 |
ac85e599683d0784167de6fb1c7d8c78
|
|
| BLAKE2b-256 |
c6dadaa2fa1a5d793a93ca98841d365427431501f3d4351ed14651a90efdac30
|
Provenance
The following attestation bundles were made for flask_unirate-0.1.0.tar.gz:
Publisher:
release.yml on UniRate-API/flask-unirate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_unirate-0.1.0.tar.gz -
Subject digest:
ea085b4dd6e0a2b7b0b1a6891d9d00a82851de032c7b46524e5cb9c985a7eed7 - Sigstore transparency entry: 1483267604
- Sigstore integration time:
-
Permalink:
UniRate-API/flask-unirate@79a73731de37c5c566b25194609155f92e9769e0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/UniRate-API
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79a73731de37c5c566b25194609155f92e9769e0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file flask_unirate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flask_unirate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9430622b176008595cf422b7bff09adfb04bdba3894d0cc88ec07a7a07acb79d
|
|
| MD5 |
2d0bc65c3f3e1de48ad2bb089bb0298f
|
|
| BLAKE2b-256 |
076ec46bb8f507f4b2ff4e5df7495334c126fb2349da0e536d29683075273f71
|
Provenance
The following attestation bundles were made for flask_unirate-0.1.0-py3-none-any.whl:
Publisher:
release.yml on UniRate-API/flask-unirate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_unirate-0.1.0-py3-none-any.whl -
Subject digest:
9430622b176008595cf422b7bff09adfb04bdba3894d0cc88ec07a7a07acb79d - Sigstore transparency entry: 1483267614
- Sigstore integration time:
-
Permalink:
UniRate-API/flask-unirate@79a73731de37c5c566b25194609155f92e9769e0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/UniRate-API
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79a73731de37c5c566b25194609155f92e9769e0 -
Trigger Event:
push
-
Statement type: