Home Documentation Pricing API Status Blog FAQ Support

How to Handle Base Currency Conversion in Your App

"How do I convert from EUR to GBP if my API only supports USD as the base currency?" This question appears in nearly every exchange rate API support forum. It is one of the most common developer pain points — and it is entirely avoidable with the right API or the right code.

The Base Currency Problem

Most exchange rate APIs return rates relative to a base (source) currency. When you call GET /rates?base=USD, you get something like:

{
  "base": "USD",
  "rates": {
    "EUR": 0.9234,
    "GBP": 0.7891,
    "JPY": 151.42
  }
}

This tells you how much 1 USD buys in each currency. But what if your users are in Europe and you need EUR to GBP? Or your app serves customers in India and you need INR to AUD?

The catch: Many free API plans lock the base currency to USD. Changing the base to EUR, GBP, or any other currency requires a paid upgrade. This forces developers into workarounds.

API Free Base Currency Any Base Currency
AllRatesToday Any currency All plans
Open Exchange Rates USD only Developer plan ($12/mo)
Fixer.io EUR only Basic plan ($10/mo)
CurrencyAPI USD only Pro plan
Frankfurter Any (ECB set) Limited to ~30 currencies

The Easy Way: Use an API That Supports Any Base

The simplest solution is to use an API that lets you set any currency as the source. With AllRatesToday, just change the source parameter:

# EUR as base
curl "https://allratestoday.com/api/v1/rates?source=EUR&target=GBP" \
  -H "Authorization: Bearer YOUR_API_KEY"

# INR as base
curl "https://allratestoday.com/api/v1/rates?source=INR&target=AUD" \
  -H "Authorization: Bearer YOUR_API_KEY"

# JPY as base, multiple targets
curl "https://allratestoday.com/api/v1/rates?source=JPY&target=USD,EUR,KRW" \
  -H "Authorization: Bearer YOUR_API_KEY"

This works on all plans, including the free tier. No workarounds needed.

The Manual Way: Cross-Rate Calculation

If you are stuck with a USD-locked API, you can calculate cross-rates yourself. The math is straightforward:

Cross-rate formula: To convert from currency A to currency B when you only have USD-based rates:

A/B = (USD/B) / (USD/A)

Or equivalently: A/B = rate_B / rate_A where both rates are USD-based.

Example: EUR to GBP

Given USD-based rates:

Cross-rate: EUR/GBP = 0.7891 / 0.9234 = 0.8546

So 1 EUR = 0.8546 GBP.

JavaScript Implementation

// Cross-rate calculation when your API only returns USD-based rates
function crossRate(usdRates, from, to) {
  if (from === 'USD') return usdRates[to];
  if (to === 'USD') return 1 / usdRates[from];
  return usdRates[to] / usdRates[from];
}

// Usage
const usdRates = {
  EUR: 0.9234,
  GBP: 0.7891,
  JPY: 151.42,
  INR: 83.45,
  AUD: 1.5312
};

console.log('EUR to GBP:', crossRate(usdRates, 'EUR', 'GBP'));  // 0.8546
console.log('GBP to JPY:', crossRate(usdRates, 'GBP', 'JPY'));  // 191.89
console.log('INR to AUD:', crossRate(usdRates, 'INR', 'AUD'));   // 0.01835

Python Implementation

def cross_rate(usd_rates: dict, source: str, target: str) -> float:
    """Calculate cross-rate from USD-based rates."""
    if source == "USD":
        return usd_rates[target]
    if target == "USD":
        return 1 / usd_rates[source]
    return usd_rates[target] / usd_rates[source]


usd_rates = {
    "EUR": 0.9234,
    "GBP": 0.7891,
    "JPY": 151.42,
    "INR": 83.45,
    "AUD": 1.5312,
}

print(f"EUR to GBP: {cross_rate(usd_rates, 'EUR', 'GBP'):.4f}")  # 0.8546
print(f"GBP to JPY: {cross_rate(usd_rates, 'GBP', 'JPY'):.2f}")  # 191.89
print(f"INR to AUD: {cross_rate(usd_rates, 'INR', 'AUD'):.5f}")   # 0.01835

Converting Amounts (Not Just Rates)

Once you have the rate, converting an amount is simple multiplication. But there are common mistakes developers make:

The Rounding Problem

// Wrong: floating-point precision issues
const amount = 1999.99;
const rate = 0.9234;
const result = amount * rate;  // 1846.7907659999998

// Right: round to the target currency's decimal places
function convertAmount(amount, rate, decimals = 2) {
  return Number((amount * rate).toFixed(decimals));
}

console.log(convertAmount(1999.99, 0.9234));  // 1846.79

// For JPY (0 decimals)
console.log(convertAmount(1999.99, 151.42, 0));  // 302840

Currency decimal places: Most currencies use 2 decimal places, but JPY, KRW, VND use 0. BHD, KWD, OMR use 3. Always round to the correct number of decimals for the target currency.

Using the AllRatesToday SDK

The SDK handles base currency and conversion in a single call:

import AllRatesToday from '@allratestoday/sdk';

const client = new AllRatesToday('YOUR_API_KEY');

// Direct conversion - any base currency, any target
const result = await client.convert('EUR', 'GBP', 5000);
console.log(`5,000 EUR = ${result.result} GBP`);

// Get rate for any pair directly
const rate = await client.getRate('INR', 'AUD');
console.log(`1 INR = ${rate} AUD`);

Handling Multiple Target Currencies

A common pattern is showing a price in the user's local currency. Here is an efficient approach:

import AllRatesToday from '@allratestoday/sdk';

const client = new AllRatesToday('YOUR_API_KEY');

// Fetch all rates from your store's base currency in one call
const rates = await client.getRates('USD');

// Convert a product price to any visitor's currency
function displayPrice(priceUSD, targetCurrency) {
  const rate = rates[targetCurrency];
  const converted = (priceUSD * rate).toFixed(2);
  return `${converted} ${targetCurrency}`;
}

// Display for different visitors
console.log(displayPrice(99.99, 'EUR'));  // "92.32 EUR"
console.log(displayPrice(99.99, 'GBP'));  // "78.90 GBP"
console.log(displayPrice(99.99, 'JPY'));  // "15141 JPY"

Performance tip: Fetch rates once per minute and cache them. AllRatesToday updates every 60 seconds, so there is no benefit to fetching more frequently. This keeps you well within the free tier's 300 requests/month.

Summary

Any Base Currency. Any Plan.

AllRatesToday supports all 160+ currencies as the source — even on the free tier. No cross-rate workarounds needed.

Get Your Free API Key