惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
博客园_首页
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
B
Blog RSS Feed
D
Docker
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A
About on SuperTechFans
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
V
V2EX
量子位
雷峰网
雷峰网
月光博客
月光博客
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How I Built and Monetized a Currency Exchange Rate API wi...
dhritich20baruah · 2026-05-30 · via DEV Community

dhritich20baruah

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:

  1. Push your code to GitHub
  2. Connect the repo to Render → New Web Service
  3. Set the start command: uvicorn main:app --host 0.0.0.0 --port 8000
  4. Add your API key as an environment variable
  5. 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:

  1. Go to rapidapi.com/provider → Add New API
  2. Add your Render URL as the Base URL
  3. Add each endpoint with its query parameters
  4. Set up freemium pricing tiers
  5. 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.