last updated:
next refresh in
Live Exchange Rate Comparison

Find the best rate.
Every time.

Click any cell in the matrix to compare banks, fintechs, remittance services, and crypto rails — including Buda, Bitso, Stellar, and Ripple ODL.

mid-market rates · open.er-api.com · rows = you send, columns = they receive

Global Balance API

Live exchange rates and provider comparison data, available as a REST API. No API key required. Deploy the included server to any Node.js host.

Base URL edit to match your deployment

Quick Start

1
Make a request — no API key needed. All endpoints are public and return JSON.
curl "https://globalbalance.dev/api/rates?from=USD&to=EUR"
2
Rates are cached for 15 minutes and refreshed by a background cron job. Every response includes a checkedAt field with the cache timestamp.
3
To embed in your own app, clone the repo, run npm install, then npm run dev to start on localhost:3000.
4
Deploy to Vercel in one command: vercel --prod. A vercel.json is included for zero-config deployment.
GET /api/rates Live mid-market rate
ParamTypeDescription
fromrequiredstringISO 4217 source currency code — e.g. USD, EUR, GBP
torequiredstringISO 4217 target currency code — e.g. INR, MXN, BRL
Response Schema
FieldTypeDescription
okbooleanAlways true on success
fromstringSource currency code
tostringTarget currency code
ratenumberMid-market exchange rate (1 unit of from in to)
sourcestringData provider that returned this rate — e.g. open.er-api.com
timestampstringUTC timestamp of the underlying source data
checkedAtstringUTC timestamp when this response was generated / served from cache
Try it

      
const res = await fetch(`${API_BASE}/api/rates?from=USD&to=INR`); const data = await res.json(); // { ok: true, from: "USD", to: "INR", rate: 83.42, source: "open.er-api.com", timestamp: "...", checkedAt: "..." }
GET /api/compare Provider comparison
ParamTypeDescription
fromrequiredstringISO 4217 source currency
torequiredstringISO 4217 target currency
amountoptionalnumberAmount to send in source currency. Default: 1000
sortoptionalstringSort order: rate | fee | spread. Default: rate
Response Schema
FieldTypeDescription
okbooleanAlways true on success
from / tostringCurrency pair
amountnumberSend amount used for calculations
midRatenumberInterbank mid-market rate used as baseline
providersarrayList of provider result objects (see below)
bestProviderstringName of the top-ranked provider for this pair
maxSavingsnumberDifference in destination amount between best and worst provider
checkedAtstringUTC timestamp when this response was generated
Provider Object
FieldTypeDescription
ranknumber1 = best
id / namestringProvider identifier and display name
typestringCategory — Fintech, Bank, Crypto, etc.
receiveAmountnumberDestination currency amount recipient receives
effectiveRatenumberAll-in rate after fees and spread
spreadPctnumberFX markup percentage (0 = mid-market)
totalFeenumberTotal fee in source currency units
network / sourcestringTransfer network and data source label
dataNotestringFee data provenance and date
Try it

      
const res = await fetch(`${API_BASE}/api/compare?from=USD&to=MXN&amount=1000&sort=rate`); const { providers, bestProvider, maxSavings } = await res.json(); // providers[0] = { rank: 1, name: "Stellar / USDC", receiveAmount: 17324.5, ... }
GET /api/matrix Cross-rate matrix
ParamTypeDescription
currenciesoptionalstringComma-separated ISO 4217 codes. Max 10. Default: USD,EUR,GBP,JPY,CAD,MXN,INR,BRL
Response Schema
FieldTypeDescription
okbooleanAlways true on success
basestringPivot currency used to compute cross-rates
ratesobjectNested object — rates[from][to] gives the exchange rate
sourcestringData provider for the base rates
timestampstringUTC timestamp of the underlying source data
Try it

      
const res = await fetch(`${API_BASE}/api/matrix?currencies=USD,EUR,GBP,INR,MXN`); const { rates } = await res.json(); // rates["USD"]["INR"] → 83.42 // rates["EUR"]["MXN"] → 19.87
GET /api/providers Provider metadata

Returns all supported providers with fee structures, network info, and data source metadata. No parameters required.

Response Schema — Provider Object
FieldTypeDescription
idstringMachine-readable identifier — e.g. wise, paypal
namestringDisplay name
typestringCategory — Fintech, Bank, Crypto, Crypto/Stablecoin
networkstringTransfer rail — e.g. SWIFT, SEPA, Blockchain
spreadPctnumberFX markup as a decimal (0.005 = 0.5%)
feeFixednumberFixed fee in source currency units
feePctnumberPercentage fee (0.01 = 1%)
feeUrlstringURL to the official fee schedule page
dataNotestringFee data provenance, corridor, and collection date
supportedFromstring | array"any" or list of supported source currency codes
supportedTostring | array"any" or list of supported destination currency codes
Try it

      
const res = await fetch(`${API_BASE}/api/providers`); const { providers } = await res.json(); // [{ id: "wise", name: "Wise", type: "Fintech", spreadPct: 0, feeUrl: "...", ... }]
GET /api/history Historical rates

Returns stored historical mid-market rates for a currency pair, sampled every 15 minutes. History is accumulated from the first /api/refresh call and stored in Redis — up to 30 days of data.

ParamTypeDescription
fromrequiredstringISO 4217 source currency code
torequiredstringISO 4217 target currency code
daysoptionalnumberNumber of days of history to return. Default: 7. Max: 30
Response Schema
FieldTypeDescription
okbooleanAlways true on success
from / tostringCurrency pair
daysnumberDays of history requested
dataarrayChronological list of rate snapshots
data[].tsstringISO 8601 timestamp of this snapshot
data[].ratenumberMid-market rate at this timestamp
Try it

      
const res = await fetch(`${API_BASE}/api/history?from=USD&to=EUR&days=7`); const { data } = await res.json(); // data = [{ ts: "2026-04-06T14:00:00Z", rate: 0.9214 }, ...] data.forEach(d => console.log(d.ts, d.rate));

Rate Limits

The Global Balance API is currently open with no enforced per-client rate limits. All responses are served from a 15-minute Redis cache to protect upstream data providers.

LimitValueNotes
Cache TTL (fiat)15 minRates are refreshed by cron; stale data may be served until the next refresh cycle
Cache TTL (crypto)2 minCoinbase BTC/ETH rates refresh more frequently
Matrix currencies10 maxThe /api/matrix endpoint caps the currencies param at 10 codes
History window30 daysRedis list is trimmed to the last 2,880 snapshots (30d × 96 per day)
Vercel Hobby~100 req/sVercel's edge limits apply to the serverless functions; contact Vercel for higher tiers

Error Codes

All errors return a JSON body with { "error": "..." } and an appropriate HTTP status code.

StatusCodeDescription
400Bad RequestMissing or invalid required parameters — e.g. missing from or to
404Not FoundUnknown route. Check the path and method.
500Upstream ErrorAll upstream rate providers failed to respond. Retry after a few seconds.
503Service UnavailableRate cache is cold (Redis not yet warmed). Try again after the first cron run.
// Error response shape { "error": "Missing required param: from" }

Changelog

Apr 2026
v1.3 — History endpoint & dynamic providers Added /api/history for time-series rate data (Redis-backed, 30d window). Provider list is now dynamic per currency corridor — only relevant providers appear.
Mar 2026
v1.2 — Twelve Data + Redis caching Integrated Twelve Data for intraday fiat rates on pair lookups. Switched to Upstash Redis for persistent 15-minute cache across serverless invocations. External cron via cron-job.org.
Mar 2026
v1.1 — Custom domain & fee data refresh Published to globalbalance.dev. Updated provider fee schedules for Revolut, Remitly, Western Union, MoneyGram, and PayPal from current published tariffs.
Feb 2026
v1.0 — Initial release Exchange rate comparison across 17 providers. Mid-market rates from open.er-api.com and Coinbase. Static HTML frontend + Express API on Vercel.

Resources

Download the machine-readable API specification or import directly into Postman.

The API server is in api/index.js. Run npm install then choose a host:

Vercel recommended

Free tier, zero config. vercel.json is included — just connect your repo or drag the folder.

↗ vercel.com/new

Railway

Connect your GitHub repo. Set start command to node api/index.js. Free tier available.

↗ railway.app

Local

Run locally for development. npm install && npm run dev starts the server with auto-reload.

npm install
npm run dev