API Documentation

Everything you need to integrate real-time currency exchange rates into your application.

Get Free API Key → Quickstart Guide
No credit card required · Setup in 30 seconds

Quickstart — Get Started in < 2 Minutes

  1. Sign up free → Get your API key from the dashboard
  2. Copy your API key (starts with era_live_)
  3. Try this request:
curl "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR" \
  -H "Authorization: Bearer era_live_YOUR_API_KEY"

Don't have an account? Create one for free.

Overview

The Exchange Rate API provides real-time and historical currency exchange rates via a simple REST interface. All responses are JSON. The base URL is:

https://exchange-rateapi.com

We offer multiple plans with varying rate limits. All authenticated endpoints require an API key sent as a Bearer token. See our pricing page for details.

Authentication

All API endpoints (except /api/rate and /api/v1/symbols) require authentication. Include your API key as a Bearer token in the Authorization header:

Authorization: Bearer era_live_YOUR_API_KEY

Get your API key from your dashboard after signing up.

API Key Format Live keys are prefixed with era_live_ and test keys with era_test_. This makes accidental logging easier to spot in your codebase.

Security

The Exchange Rate API is designed with security as a first-class concern. This section explains the transport, authentication, and data-handling guarantees you can rely on, plus the responsibilities that sit on your side as an integrator.

Transport (TLS / HTTPS)

  • All API traffic must be sent over HTTPS. Plain-text HTTP requests are permanently redirected (301) to HTTPS but should never be used for API calls — the redirect leaks your API key via the initial request.
  • We require TLS 1.2 or higher. Connections using older TLS versions (1.0, 1.1) or SSLv3 are rejected at the edge.
  • Certificates are issued by publicly-trusted CAs and automatically renewed. HSTS is enforced with max-age=31536000; includeSubDomains.

Authentication

  • Authentication uses a Bearer token in the Authorization header — no query-string keys (which get logged by proxies, CDNs, and browser history).
  • Every API key is scoped to one account and can be rotated or revoked instantly from your dashboard.
  • Keys are stored server-side as hashed values — even we cannot read your key after you generate it. If lost, generate a new one.
  • Live keys are prefixed with era_live_, test keys with era_test_. This makes accidental logging easier to spot.

API Key Handling (Your Responsibilities)

Never embed your API key in client-side code. Browsers, mobile apps, and any compiled binary can be decompiled. A key shipped to the browser is a public key — expect it to be scraped within hours.
  • Server-side only. Call the Exchange Rate API from your backend. Proxy the result to your frontend.
  • Use environment variables (process.env.ERA_API_KEY). Never commit keys to git, never include them in container images.
  • Rotate keys periodically — at minimum every 90 days, and immediately if a key is ever exposed in logs, commits, or error reports.
  • Use one key per service. When a key leaks, you can revoke just that environment instead of rotating everything.

Abuse Protection

  • Rate limiting is applied per API key (see Rate Limits). Exceeding the limit returns 429 Too Many Requests; it does not leak usage data to other keys.
  • WAF & DDoS: requests are filtered by Cloudflare's edge network, which applies OWASP Top 10 mitigations automatically. Malformed or abusive requests are rejected before reaching the API.
  • Automated monitoring flags anomalous usage patterns (e.g. sudden 100x spikes) and can lock a key pending verification.

Data Handling & Privacy

  • We log request metadata (timestamp, endpoint, status code, rate-limit counters) but never the response payload. Rate data is public.
  • We do not collect or store any personal data you send in query strings — but please don't send any: all the API needs is currency codes and optional date parameters.
  • Access logs are retained for 30 days for debugging and abuse investigation, then permanently deleted.
  • See our privacy policy for the full data-handling statement.

Reporting a Vulnerability

If you believe you have found a security issue in the Exchange Rate API, please report it privately to support@exchange-rateapi.com. Please do not disclose the issue publicly until we have had a reasonable chance to respond.

We aim to acknowledge reports within 24 hours and provide a remediation timeline within 72 hours. Responsible disclosure is credited publicly after the fix is deployed (if you want to be named).

Rate Limits

Rate Limit Headers All authenticated responses include these headers:
X-RateLimit-Limit — your monthly request allowance
X-RateLimit-Remaining — requests remaining this month
X-RateLimit-Reset — when the limit resets (ISO 8601)
PlanMonthly Requests
Free300
Small5,000
Medium10,000
Large100,000

Rate limits vary by plan. When you exceed your monthly limit, the API returns a 429 status with details about your usage and when the limit resets. A warning email is sent when you reach 90% of your monthly limit. View plans and pricing

// Example 429 response when limit exceeded
{
  "error": "Monthly request limit exceeded. Upgrade your plan for more requests.",
  "error_code": "rate_limit_exceeded",
  "status": 429,
  "used": 5000,
  "limit": 5000,
  "resets_at": "2026-06-01T00:00:00.000Z"
}

Authenticated Rates

GET /api/v1/rates

Authenticated endpoint with higher rate limits. Requires a Bearer token.

ParameterTypeDescription
sourceoptional string Source currency code (e.g. USD)
targetoptional string Target currency code (e.g. EUR). Supports comma-separated values for multiple targets (e.g. EUR,GBP,JPY)
timeoptional ISO 8601 Rate at a specific point in time
fromoptional YYYY-MM-DD Start date for historical range
tooptional YYYY-MM-DD End date for historical range
groupoptional string Group by: day, hour, minute
amountoptional number Amount to convert (default: 1). The response rate is always per unit; use this for display convenience.

Example Request:

curl "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR" \
  -H "Authorization: Bearer era_live_YOUR_API_KEY"

Response:

[
  {
    "rate": 0.9215,
    "source": "USD",
    "target": "EUR",
    "time": "2026-05-10T12:00:00Z"
  }
]

Multiple targets:

curl "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR,GBP,JPY" \
  -H "Authorization: Bearer era_live_YOUR_API_KEY"
[
  { "rate": 0.9215, "source": "USD", "target": "EUR", "time": "2026-05-10T12:00:00Z" },
  { "rate": 0.7891, "source": "USD", "target": "GBP", "time": "2026-05-10T12:00:00Z" },
  { "rate": 151.42, "source": "USD", "target": "JPY", "time": "2026-05-10T12:00:00Z" }
]

Simple Rate

GET /api/rate

Lightweight endpoint for fetching a single pair rate. No authentication required.

ParameterTypeDescription
sourcerequired string Source currency code
targetrequired string Target currency code

Example:

curl "https://exchange-rateapi.com/api/rate?source=GBP&target=USD"

Response:

{ "rate": 1.2634, "source": "refinitiv" }
What does "source": "refinitiv" mean? The source field in the response indicates the data provider. Exchange Rate API delivers mid-market exchange rates sourced from Refinitiv (Reuters) and interbank market feeds — the same institutional-grade data used by banks and financial platforms worldwide, without any retail markup.

Historical Rates

GET /api/historical-rates

Fetch historical exchange rate data for charting and analysis. Requires an API key.

ParameterTypeDescription
sourcerequired string Source currency code
targetrequired string Target currency code
periodoptional string 1d, 7d, 30d, or 1y (default: 7d)

Example:

curl "https://exchange-rateapi.com/api/historical-rates?source=USD&target=EUR&period=30d" \
  -H "Authorization: Bearer era_live_YOUR_API_KEY"

Response:

{
  "source": "USD",
  "target": "EUR",
  "data": [
    { "date": "2026-04-11", "rate": 0.9198, "timestamp": 1744329600000 },
    { "date": "2026-04-12", "rate": 0.9210, "timestamp": 1744416000000 },
    ...
  ],
  "source_api": "refinitiv",
  "period": "30d"
}
Tip Use the period parameter for preset ranges (1d, 7d, 30d, 1y). For custom date ranges, use the /api/v1/rates endpoint with from and to parameters.

Symbols

GET /api/v1/symbols

Get all supported currency codes and their full names. Use this to build currency dropdowns and selectors in your UI.

curl "https://exchange-rateapi.com/api/v1/symbols"

No authentication required. Response is cached for 24 hours.

Response:

{
  "currencies": [
    { "code": "USD", "name": "US Dollar", "symbol": "$" },
    { "code": "EUR", "name": "Euro", "symbol": "€" },
    { "code": "GBP", "name": "British Pound", "symbol": "£" },
    { "code": "JPY", "name": "Japanese Yen", "symbol": "¥" },
    ...
  ],
  "count": 48
}

SDK example:

// JavaScript -- build a currency dropdown
const data = await fetch('https://exchange-rateapi.com/api/v1/symbols').then(r => r.json());
const options = data.currencies.map(c => ({
  value: c.code,
  label: `${c.code} -- ${c.name}`,
}));
# Python
import requests
data = requests.get("https://exchange-rateapi.com/api/v1/symbols").json()
for c in data["currencies"]:
    print(f"{c['code']}: {c['name']} ({c['symbol']})")

Error Codes

Every error response includes a machine-readable error_code string for programmatic handling, a human-readable error message, and the HTTP status code.

HTTP Statuserror_codeMeaning
400 missing_parameter A required query parameter is missing (e.g. source or target).
401 auth_required Missing or invalid API key. Check your Authorization: Bearer ... header.
404 not_found The requested endpoint does not exist.
422 invalid_currency One or more currency codes are not supported. Check /api/v1/symbols.
429 rate_limit_exceeded Monthly request limit exceeded. Check X-RateLimit-Reset header or upgrade your plan.
502 upstream_error Upstream rate provider returned an error. Retry after a brief delay.
503 service_unavailable Rate service temporarily unavailable. Retry shortly.

Example error response:

{
  "error": "Authentication required. Provide an API key via Authorization: Bearer <key> header.",
  "error_code": "auth_required",
  "status": 401
}

Machine & AI Discovery

Exchange Rate API is designed for machine readability. AI agents, code generators, and API platforms can auto-discover the API using these endpoints:

EndpointDescription
/api/openapi.json OpenAPI 3.1 specification — full schema for all public endpoints, parameters, and response types.
/.well-known/ai-plugin.json AI plugin manifest — enables discovery by AI assistants and LLM tool-use platforms.

Data Freshness

Exchange Rate API provides real-time exchange rates sourced from institutional-grade forex data providers including Reuters (Refinitiv) and interbank market feeds. Unlike other providers that update once every 60 minutes, our rates are fetched live on every request, ensuring you always get the most current mid-market rates available.

Real-Time Updates Rates sourced from Reuters (Refinitiv) and interbank market feeds — no delayed or batched updates.

Supported Currencies

160+ currencies including:

Major Currencies USD, EUR, GBP, JPY, CHF, CAD, AUD, NZD
Popular Currencies INR, CNY, BRL, MXN, RUB, TRY, ZAR, SGD, HKD, KRW, THB, PHP, PKR, BDT, LKR, NGN, GHS, KES, AED, SAR, EGP, and more

Full list available via the /api/v1/symbols endpoint.

Official SDKs

Install our official SDK for your language. All SDKs support free and authenticated endpoints, currency conversion, and historical rates.

JavaScript / TypeScript (npm)

npm install @exchangerateapi/sdk
import ExchangeRateAPI from '@exchangerateapi/sdk';

const client = new ExchangeRateAPI({ apiKey: 'era_live_...' });

// Get latest rates (multiple currencies in one call)
const { rates } = await client.latest({ base: 'USD', symbols: ['EUR', 'GBP', 'JPY'] });
console.log(rates); // { EUR: 0.9234, GBP: 0.7891, JPY: 151.42 }

// Convert an amount
const result = await client.convert('USD', 'EUR', 1000);
console.log(`$1,000 = ${result.result} EUR`);

// Historical conversion at a specific date
const past = await client.convert('USD', 'EUR', 1000, { date: '2026-01-15' });

// Rates for a specific date
const data = await client.forDate('2026-01-15', { base: 'EUR', symbols: ['USD', 'GBP'] });

// List all supported currencies
const { symbols } = await client.symbols();
console.log(symbols); // { USD: 'United States Dollar', EUR: 'Euro', ... }

// Historical rates by period
const history = await client.getHistoricalRates('USD', 'EUR', '30d');

Python (pip)

pip install exchangerateapi
from exchange_rateapi import ExchangeRateAPI

client = ExchangeRateAPI(api_key="era_live_...")

# Get exchange rate
rate = client.get_rate("USD", "EUR")
print(f"1 USD = {rate['rate']} EUR")

# Convert amount
result = client.convert("USD", "EUR", 1000)
print(f"$1,000 = {result['result']} EUR")

# Historical rates
history = client.get_historical_rates("USD", "EUR", "30d")

PHP (Composer)

composer require exchangerateapi/sdk
use ExchangeRateAPI\ExchangeRateAPI;

$client = new ExchangeRateAPI('era_live_...');

// Get exchange rate
$rate = $client->getRate('USD', 'EUR');
echo "1 USD = {$rate['rate']} EUR";

// Convert amount
$result = $client->convert('USD', 'EUR', 1000);
echo "$1,000 = {$result['result']} EUR";

// Historical rates
$history = $client->getHistoricalRates('USD', 'EUR', '30d');

Code Examples (without SDK)

You can call the API directly using any HTTP client. Here are examples in popular languages.

JavaScript / Node.js

const response = await fetch(
  'https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR',
  { headers: { 'Authorization': 'Bearer era_live_YOUR_API_KEY' } }
);
const data = await response.json();
console.log(`1 USD = ${data[0].rate} EUR`);

Python

import requests

response = requests.get(
    'https://exchange-rateapi.com/api/v1/rates',
    params={'source': 'USD', 'target': 'EUR'},
    headers={'Authorization': 'Bearer era_live_YOUR_API_KEY'}
)
data = response.json()
print(f"1 USD = {data[0]['rate']} EUR")

PHP

$opts = ['http' => ['header' => 'Authorization: Bearer era_live_YOUR_API_KEY']];
$context = stream_context_create($opts);
$response = file_get_contents(
    'https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR',
    false, $context
);
$data = json_decode($response, true);
echo "1 USD = " . $data[0]['rate'] . " EUR";

cURL

curl "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR" \
  -H "Authorization: Bearer era_live_YOUR_API_KEY"

API Playground

Try the free /api/rate endpoint directly from your browser. No API key needed for this endpoint.

GET /api/rate?source=USD&target=EUR
Click "Try it" to see the live response...
Want higher limits and more features? The playground uses the free /api/rate endpoint. For authenticated endpoints with multi-target support, historical data, and higher limits, get your free API key.

Update Frequency

Exchange rates are refreshed on every request using live interbank feeds from Reuters/Refinitiv. The frequency at which fresh data is available depends on your plan:

PlanUpdate FrequencyData Source
FreeEvery 60 secondsReuters/Refinitiv interbank
SmallEvery 60 secondsReuters/Refinitiv interbank
MediumEvery 60 secondsReuters/Refinitiv interbank
LargeEvery 60 secondsReuters/Refinitiv interbank

All plans receive the same data quality and update frequency. Rates reflect mid-market prices — the midpoint between buy and sell with no markup or spread applied.

How is this different from competitors? Many API providers restrict real-time updates to paid plans and serve daily or hourly snapshots on their free tier. Exchange Rate API delivers live 60-second updates on every plan, including Free.

Historical Data Depth

Historical exchange rate data is available on paid plans via the /api/historical-rates and /api/v1/rates endpoints.

PeriodParameterDescription
1 Dayperiod=1dHourly data points for the last 24 hours
7 Daysperiod=7dDaily data points for the last week
30 Daysperiod=30dDaily data points for the last month
1 Yearperiod=1yDaily data points for the last year
Custom Rangefrom & toSpecify exact start and end dates (YYYY-MM-DD)

The group parameter controls data granularity: minute, hour, or day. All 160+ currencies are supported for historical queries.

Historical data availability Historical rates are available from January 2021 onwards for all supported currencies. Data for major pairs (USD, EUR, GBP, JPY, CHF) extends further back. Historical endpoints are not available on the Free plan.

Volatile & Restricted Currencies

Some currencies experience extreme volatility or operate under capital controls, which can cause significant gaps between official and parallel market rates. Be aware of these when building financial applications:

CodeCurrencyNote
ARSArgentine PesoMultiple exchange rates exist (official, blue dollar, MEP). API returns official rate.
VESVenezuelan BolívarHyperinflation history. Rates can diverge significantly from street rates.
ZWLZimbabwean DollarParallel market rates may differ substantially from official rates.
SSPSouth Sudanese PoundLimited liquidity. Rates may not reflect actual market conditions.
SYPSyrian PoundConflict-affected. Official rates may not match informal markets.
LYDLibyan DinarDual exchange rate system. API returns central bank rate.
YERYemeni RialConflict-affected with divergent regional rates.

KPW (North Korean Won) is not supported due to international sanctions and the absence of a functioning foreign exchange market.

Recommendation If your application processes payments in these currencies, verify rates against multiple sources and consider adding a spread buffer to account for market discrepancies. Our API returns interbank mid-market rates sourced from Reuters/Refinitiv, which represent the best available institutional pricing.

Caching & Usage Policy

We encourage responsible use of the API to build great applications. Here are the key policies:

Caching

You may cache API responses on your servers. In fact, we recommend it — caching reduces your request count, improves your app’s response time, and ensures graceful handling of network issues. A cache TTL of 60–300 seconds is recommended for most use cases.

Permitted Use

  • Commercial and personal applications
  • Internal tools and dashboards
  • E-commerce, fintech, and SaaS products
  • Academic research and educational projects
  • Mobile applications (via server-side proxy recommended)

Prohibited Use

  • Redistributing raw rate data as a competing API service
  • Scraping or bulk downloading entire rate datasets for resale
  • Circumventing rate limits via multiple accounts
  • Using the API for any illegal or sanctioned activity

For questions about specific use cases, contact us.

More Code Examples

In addition to the JavaScript, Python, PHP, and cURL examples above, here are examples in other popular languages.

Java

import java.net.http.*;
import java.net.URI;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR"))
    .header("Authorization", "Bearer era_live_YOUR_KEY")
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

Ruby

require 'net/http'
require 'json'

uri = URI("https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer era_live_YOUR_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
  http.request(req)
}
data = JSON.parse(res.body)
puts data

Go

package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET",
        "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR", nil)
    req.Header.Set("Authorization", "Bearer era_live_YOUR_KEY")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}

C#

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer era_live_YOUR_KEY");

var response = await client.GetStringAsync(
    "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR");
Console.WriteLine(response);

Rust

let client = reqwest::Client::new();
let resp = client
    .get("https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR")
    .header("Authorization", "Bearer era_live_YOUR_KEY")
    .send()
    .await?
    .text()
    .await?;
println!("{}", resp);

Postman Collection

Explore and test the Exchange Rate API directly in Postman. Our published collection includes all endpoints with pre-configured requests, example responses, and environment variables so you can start making calls instantly.

View the full API documentation on Postman →

Ready to integrate?

Get your free API key and start making requests in seconds.

Get Free API Key →