Everything you need to integrate real-time currency exchange rates into your application.
era_live_)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.
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.
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.
era_live_ and test keys with era_test_. This makes accidental logging easier to spot in your codebase.
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.
301) to HTTPS but should never be used for API calls — the redirect leaks your API key via the initial request.max-age=31536000; includeSubDomains.Authorization header — no query-string keys (which get logged by proxies, CDNs, and browser history).era_live_, test keys with era_test_. This makes accidental logging easier to spot.process.env.ERA_API_KEY). Never commit keys to git, never include them in container images.429 Too Many Requests; it does not leak usage data to other keys.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).
X-RateLimit-Limit — your monthly request allowanceX-RateLimit-Remaining — requests remaining this monthX-RateLimit-Reset — when the limit resets (ISO 8601)
| Plan | Monthly Requests |
|---|---|
| Free | 300 |
| Small | 5,000 |
| Medium | 10,000 |
| Large | 100,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 endpoint with higher rate limits. Requires a Bearer token.
| Parameter | Type | Description |
|---|---|---|
| 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" }
]
Lightweight endpoint for fetching a single pair rate. No authentication required.
| Parameter | Type | Description |
|---|---|---|
| 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" }
"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.
Fetch historical exchange rate data for charting and analysis. Requires an API key.
| Parameter | Type | Description |
|---|---|---|
| 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"
}
period parameter for preset ranges (1d, 7d, 30d, 1y). For custom date ranges, use the /api/v1/rates endpoint with from and to parameters.
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']})")
Every error response includes a machine-readable error_code string for programmatic handling, a human-readable error message, and the HTTP status code.
| HTTP Status | error_code | Meaning |
|---|---|---|
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
}
Exchange Rate API is designed for machine readability. AI agents, code generators, and API platforms can auto-discover the API using these endpoints:
| Endpoint | Description |
|---|---|
/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. |
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.
160+ currencies including:
Full list available via the /api/v1/symbols endpoint.
Install our official SDK for your language. All SDKs support free and authenticated endpoints, currency conversion, and historical rates.
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');
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")
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');
You can call the API directly using any HTTP client. Here are examples in popular languages.
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`);
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")
$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 "https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR" \
-H "Authorization: Bearer era_live_YOUR_API_KEY"
Try the free /api/rate endpoint directly from your browser. No API key needed for this endpoint.
/api/rate?source=USD&target=EUR
Click "Try it" to see the live response...
/api/rate endpoint. For authenticated endpoints with multi-target support, historical data, and higher limits, get your free API key.
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:
| Plan | Update Frequency | Data Source |
|---|---|---|
| Free | Every 60 seconds | Reuters/Refinitiv interbank |
| Small | Every 60 seconds | Reuters/Refinitiv interbank |
| Medium | Every 60 seconds | Reuters/Refinitiv interbank |
| Large | Every 60 seconds | Reuters/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.
Historical exchange rate data is available on paid plans via the /api/historical-rates and /api/v1/rates endpoints.
| Period | Parameter | Description |
|---|---|---|
| 1 Day | period=1d | Hourly data points for the last 24 hours |
| 7 Days | period=7d | Daily data points for the last week |
| 30 Days | period=30d | Daily data points for the last month |
| 1 Year | period=1y | Daily data points for the last year |
| Custom Range | from & to | Specify 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.
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:
| Code | Currency | Note |
|---|---|---|
| ARS | Argentine Peso | Multiple exchange rates exist (official, blue dollar, MEP). API returns official rate. |
| VES | Venezuelan Bolívar | Hyperinflation history. Rates can diverge significantly from street rates. |
| ZWL | Zimbabwean Dollar | Parallel market rates may differ substantially from official rates. |
| SSP | South Sudanese Pound | Limited liquidity. Rates may not reflect actual market conditions. |
| SYP | Syrian Pound | Conflict-affected. Official rates may not match informal markets. |
| LYD | Libyan Dinar | Dual exchange rate system. API returns central bank rate. |
| YER | Yemeni Rial | Conflict-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.
We encourage responsible use of the API to build great applications. Here are the key policies:
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.
For questions about specific use cases, contact us.
In addition to the JavaScript, Python, PHP, and cURL examples above, here are examples in other popular languages.
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());
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
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))
}
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);
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);
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.