Introduction:
In order to build passive income streams, I decided to publish APIs on RapidAPI. The idea is straightforward: build a useful API once, set up freemium pricing tiers, and earn recurring monthly income from subscribers.
In this post we will see how I built a Currency Exchange Rate API using FastAPI and Python, deployed it on Render, and published it on RapidAPI. I'll walk through the entire process including a debugging issue that cost me a few hours and might save you the same frustration.
The Tech Stack
FastAPI — chose this over Flask and Express because it auto-generates interactive API documentation at /docs out of the box, which is extremely useful when setting up and testing endpoints before publishing
Python — straightforward for API work, massive community support
ExchangeRate-API — free data source providing live rates for 160+ currencies, no scraping needed
Render — free tier hosting with simple GitHub deployment
RapidAPI — marketplace where developers discover and subscribe to APIs
The Three Endpoints
# 1. Get latest rates for any base currency
GET /latest?base=USD
# 2. Convert between two currencies
GET /convert?from=USD&to=INR&amount=100
# 3. List all supported currencies
GET /currencies
Here's the core conversion endpoint:
@app.get("/convert")
async def convert_currency(
from_currency: str = Query(alias="from"),
to_currency: str = Query(alias="to"),
amount: float = Query(default=1.0)
):
from_currency = from_currency.upper()
to_currency = to_currency.upper()
async with httpx.AsyncClient() as client:
response = await client.get(
f"{BASE_URL}/pair/{from_currency}/{to_currency}/{amount}"
)
data = response.json()
return {
"from": from_currency,
"to": to_currency,
"amount": amount,
"rate": data["conversion_rate"],
"converted": data["conversion_result"],
"date": data["time_last_update_utc"]
}
The Debugging Problem I faced
I originally built the API using Frankfurter (api.frankfurter.app) as the data source — it's free, requires no API key, and is backed by the European Central Bank. Perfect on paper.
The problem: when I tested with curl in the terminal, Frankfurter returned data perfectly. But when FastAPI made the same request using httpx, I kept getting this error:
{"detail": "Could not fetch rates for base currency: USD"}
After some debugging I ran this:
python -c "import urllib.request; print(urllib.request.urlopen('https://api.frankfurter.dev/latest').read())"
And got back:
urllib.error.HTTPError: HTTP Error 403: Forbidden
Frankfurter was blocking Python requests because they didn't include a browser-like User-Agent header. The server was rejecting anything that looked like a script.
I tried adding a User-Agent header to httpx but the issue persisted on my network. The clean fix was switching to ExchangeRate-API which has a proper free tier, returns consistent JSON, and works reliably with Python requests.
If you hit a 403 from a data source that works fine in the browser but fails in Python — check your User-Agent header first, and if that doesn't work, switch to a more developer-friendly data source.
Deploying on Render
Render's free tier is enough to get started. The setup takes about 5 minutes:
- Push your code to GitHub
- Connect the repo to Render → New Web Service
- Set the start command: uvicorn main:app --host 0.0.0.0 --port 8000
- Add your API key as an environment variable
- Deploy
One important note — store your API key as an environment variable on Render, not hardcoded in your code. Use python-dotenv locally and os.getenv() to read it:
import os
from dotenv import load_dotenv
load_dotenv()
EXCHANGE_RATE_API_KEY = os.getenv("EXCHANGE_RATE_API_KEY")
The free tier has one limitation — cold starts. After 15 minutes of inactivity Render spins down your service and the first request takes 30-60 seconds to wake up. Upgrade to the $7/month starter plan once you have paying subscribers — your first subscriber covers the cost.
Publishing on RapidAPI
Once your API is live on Render, publishing on RapidAPI takes about 20 minutes:
- Go to rapidapi.com/provider → Add New API
- Add your Render URL as the Base URL
- Add each endpoint with its query parameters
- Set up freemium pricing tiers
- Write a README and submit for review RapidAPI review takes 24-48 hours. Once approved your API is discoverable by thousands of developers searching the marketplace.
Closing
The full API is live on RapidAPI — https://rapidapi.com/dhritibaruah20/api/currency-exchange-rate-api9. Free tier available with 100 requests/month.
I'm also building more APIs as part of a broader strategy to generate passive income as a developer.
Top comments (0)