A real-time currency exchange rate API that aggregates USD to BRL quotes from multiple Brazilian financial platforms. Built as part of the Pluggy Full-Stack Challenge.
This REST API collects, normalizes, and analyzes USD to BRL (Dollar to Brazilian Real) exchange rates from three major sources:
- Wise - International money transfer service
- Nubank - Leading Brazilian digital bank
- Nomad - Global financial platform
The API provides real-time quotes, calculates averages, and computes slippage percentages to help users find the best exchange rates.
- β Real-time data scraping from multiple sources
- β TypeScript for type safety
- β In-memory caching (60-second TTL)
- β Comprehensive error handling
- β CORS enabled for frontend integration
- β Graceful shutdown handling
- β Retry mechanisms with exponential backoff
- β Rate validation and sanity checks
- β Deployed on Heroku
GET /quotesReturns an array of current exchange rate quotes from all available sources.
Response Example:
[
{
"buy_price": 5.8234,
"sell_price": 5.7456,
"source": "https://wise.com/es/currency-converter/brl-to-usd-rate",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"mid_market_rate": 5.7845,
"spread_percentage": 0.0067,
"currency_pair": "USD/BRL",
"provider": "Wise"
}
},
{
"buy_price": 5.8123,
"sell_price": 5.8123,
"source": "https://nubank.com.br/dados-abertos/taxas-conversao",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"date": "22/10/2025",
"currency_pair": "USD/BRL",
"provider": "Nubank",
"note": "Rate for international credit card purchases"
}
},
{
"buy_price": 5.8567,
"sell_price": 5.7234,
"source": "https://www.nomadglobal.com",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"mid_market_rate": 5.7900,
"spread_percentage": 1.15,
"currency_pair": "USD/BRL",
"provider": "Nomad Global",
"note": "Includes IOF tax and spread"
}
}
]GET /averageReturns the arithmetic mean of buy and sell prices across all sources.
Response Example:
{
"average_buy_price": 5.8308,
"average_sell_price": 5.7604,
"timestamp": "2025-10-22T14:30:00.000Z",
"sources_count": 3,
"additional_info": {
"calculation_method": "arithmetic_mean",
"sources": [
"https://wise.com/es/currency-converter/brl-to-usd-rate",
"https://nubank.com.br/dados-abertos/taxas-conversao",
"https://www.nomadglobal.com"
]
}
}GET /slippageReturns the percentage difference between each source's rates and the market average.
Response Example:
[
{
"buy_price_slippage": -0.13,
"sell_price_slippage": -0.26,
"source": "https://wise.com/es/currency-converter/brl-to-usd-rate",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"quote_buy_price": 5.8234,
"quote_sell_price": 5.7456,
"average_buy_price": 5.8308,
"average_sell_price": 5.7604,
"provider": "Wise"
}
},
{
"buy_price_slippage": -0.32,
"sell_price_slippage": 0.90,
"source": "https://nubank.com.br/dados-abertos/taxas-conversao",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"quote_buy_price": 5.8123,
"quote_sell_price": 5.8123,
"average_buy_price": 5.8308,
"average_sell_price": 5.7604,
"provider": "Nubank"
}
},
{
"buy_price_slippage": 0.44,
"sell_price_slippage": -0.64,
"source": "https://www.nomadglobal.com",
"timestamp": "2025-10-22T14:30:00.000Z",
"additional_info": {
"quote_buy_price": 5.8567,
"quote_sell_price": 5.7234,
"average_buy_price": 5.8308,
"average_sell_price": 5.7604,
"provider": "Nomad Global"
}
}
]GET /Returns API information and available endpoints.
Response Example:
{
"message": "Pluggy Full-Stack Challenge - Currency Exchange API",
"endpoints": {
"quotes": "GET /quotes - Get all exchange rate quotes",
"average": "GET /average - Get average exchange rates",
"slippage": "GET /slippage - Get slippage percentages"
},
"documentation": "See README.md for more details",
"version": "1.0.0"
}- Runtime: Node.js
- Language: TypeScript
- Framework: Express.js
- Web Scraping: Puppeteer
- HTTP Client: Axios
- Deployment: Heroku
- Node.js 18+
- npm or yarn
-
Clone the repository
git clone <your-repo-url> cd brl-quotes-api
-
Install dependencies
npm install
-
Run development server
npm run dev
The API will be available at
http://localhost:3000 -
Build for production
npm run build
-
Start production server
npm start
brl-quotes-api/
βββ src/
β βββ index.ts # Express server setup
β βββ types.ts # TypeScript interfaces
β βββ routes/
β β βββ quotes.routes.ts # API route definitions
β βββ services/
β β βββ quotes.service.ts # Business logic & caching
β βββ data-sources/
β βββ wise.ts # Wise scraper
β βββ nubank.ts # Nubank scraper
β βββ nomad.ts # Nomad API client
βββ dist/ # Compiled JavaScript (generated)
βββ package.json
βββ tsconfig.json
βββ README.md
- Request β API endpoint receives request
- Cache Check β Service checks if cached data is valid (<60s old)
- Data Collection β If cache expired, scrapes/fetches from all sources in parallel
- Processing β Calculates averages and slippage
- Response β Returns formatted JSON response
- Cache Update β Stores results with timestamp
- Wise: Puppeteer web scraping with DOM parsing
- Nubank: Puppeteer scraping from public data table
- Nomad: Direct API call with axios
- Retry mechanism with exponential backoff (3 attempts)
- Rate validation (checks if values are within reasonable ranges)
- Partial failure support (API works even if one source fails)
- Detailed error logging
- Cache Duration: 60 seconds
- Cache Strategy: In-memory caching
- Cache Invalidation: Automatic after TTL expires
- Fresh Data: Always fetches new data if cache is stale
All error responses follow this format:
{
"error": "Error Type",
"message": "Detailed error message",
"timestamp": "2025-10-22T14:30:00.000Z"
}Common HTTP status codes:
200- Success404- Endpoint not found500- Internal server error (scraping failure, etc.)
Deployed on Heroku with the following configuration:
Buildpacks:
heroku/nodejsjontewks/puppeteer(for Chromium dependencies)
Environment Variables:
PORT: Automatically set by Heroku
Start Command:
"start": "node dist/index.js"| Source | Type | Update Frequency | Reliability |
|---|---|---|---|
| Wise | Web Scraping | Real-time | High |
| Nubank | Web Scraping | Daily | High |
| Nomad | API | Real-time | High |
- Compare exchange rates across platforms
- Find the best USD to BRL conversion rate
- Track rate volatility and spreads
- Integrate into financial dashboards
- Market analysis and research
ThaΓs Rodeiro
This is a challenge project, but suggestions and feedback are welcome!
Built with β€οΈ for the Pluggy Full-Stack Challenge