Integration guide
Add currency exchange rates and conversion to FastAPI
Use FastAPI with httpx.AsyncClient. Cache latest rates until nextUpdateAt and keep the key in server configuration.
1. Get a free API key
Sign up at https://currencyexchangerate-api.com/auth/login, then create a key under API keys in the console. The free plan includes 3,000 requests per month with no credit card. Store the secret as CXR_API_KEY in server-side environment configuration; never expose it in browser code.
.env
shellCXR_API_KEY=cxr_your_secret_key2. Create a reusable client and cache rates
Use the standard HTTP client. Cache every /latest response until nextUpdateAt: rates change at most once by then, and reusing the response saves quota. The helper also exposes /convert.
rates.py
Pythonimport osimport timefrom datetime import datetime import httpx API_BASE_URL = 'https://api.currencyexchangerate-api.com/api/v1'HEADERS = {'Authorization': 'Bearer ' + os.environ['CXR_API_KEY']}_cache = None async def latest(client: httpx.AsyncClient): global _cache if _cache and time.time() < _cache[0]: return _cache[1] response = await client.get( API_BASE_URL + '/latest', params={'base': 'USD', 'symbols': 'EUR,GBP'}, headers=HEADERS, ) response.raise_for_status() data = response.json() next_update = data['nextUpdateAt'].replace('Z', '+00:00') until = datetime.fromisoformat(next_update).timestamp() _cache = (until, data) return data async def convert(client: httpx.AsyncClient, source, target, amount): response = await client.get( API_BASE_URL + '/convert', params={'from': source, 'to': target, 'amount': amount}, headers=HEADERS, ) response.raise_for_status() return response.json()3. Use it in FastAPI
Call the helper from a server route, controller, view, command, or script. Format converted values for the user’s locale.
main.py
Pythonimport httpxfrom fastapi import FastAPI from rates import convert app = FastAPI() @app.get('/convert')async def conversion(source: str = 'EUR', target: str = 'GBP', amount: float = 100): async with httpx.AsyncClient() as client: data = await convert(client, source, target, amount) formatted = f"{data['result']:,.2f} {data['to']}" return {**data, 'formatted': formatted}4. Handle API errors
A 401 means the key is invalid. A 429 can mean a rate limit or quota limit; read Retry-After in seconds before retrying. Other errors use application/problem+json.
errors.py
Pythonimport httpxfrom fastapi import HTTPException from rates import convert async def safe_convert(client, source, target, amount): try: return await convert(client, source, target, amount) except httpx.HTTPStatusError as error: response = error.response retry = response.headers.get('Retry-After') raise HTTPException( response.status_code, response.json().get('detail', 'Rates API error'), headers={'Retry-After': retry} if retry else None, ) from error5. Format the amount for display
Use locale-aware currency formatting instead of adding a symbol manually.
format.py
Python# pip install babelfrom babel.numbers import format_currency print(format_currency(85.249105, 'EUR', locale='en_GB'))