Overview
Lume Exchange Rates brings exchange-rate comparison, conversion and historical charts into one place. Choose the currencies that matter to you, whether you are planning a trip, comparing an international price or building a product.
We use External exchange-rate provider as the configured source. Each latest-rate response identifies its source and publication time. Available currency symbols are updated from the latest provider data.
Quick start
Read the currency catalog first, then select an anchor and targets. Field names and currency codes are identical in every interface language.
curl --request GET 'https://lumeexchangerates.com/v1/quotes?anchor=USD&targets=EUR,JPY'const response = await fetch('/v1/quotes?anchor=USD&targets=EUR,JPY', {
credentials: 'same-origin'
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { meta, anchor, data } = await response.json();
console.log(anchor, meta.as_of, data);The browser example runs on the same origin. cURL and server requests to a private site require authorized site access; the URL does not bypass its login policy.
Access & authentication
The hosted preview uses the site’s access policy and browser session. Customer API keys, Bearer-token authentication for customers and a public cross-origin API are not currently provided. Keep the provider App ID on the server; do not send it to Lume Exchange Rates endpoints.
| Parameter | Type | Description |
|---|---|---|
| Base URL | URL | https://lumeexchangerates.com |
| Content-Type | header | application/json |
| Customer API key | — | This hosted preview uses the signed-in browser session. It does not yet issue per-customer API keys. |
| Provider App ID | server secret | OPEN_EXCHANGE_RATES_APP_ID |
| CORS | same-origin | No cross-origin allow headers are currently provided. |
Authorization: Token is used only by the Lume Exchange Rates server when contacting External exchange-rate provider. It is not customer authentication. Access-control failures may be HTML or redirects from the hosting gateway: check status and Content-Type first.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/currencies | All symbols with current rates, with provider names. Includes available alternatives and metals. |
| GET | /v1/quotes | Base symbol; defaults to USD. Any current provider symbol is accepted. |
| GET | /v1/exchange | Non-negative numeric amount to convert. |
| GET | /v1/history | Daily history and date-range series are available through /v1/history and /v1/series. |
| GET | /v1/series | Daily history and date-range series are available through /v1/history and /v1/series. |
| GET | /v1/candles | OHLC |
| GET | /v1/capabilities | Availability |
| GET | /api/rates/latest | Latest published rate |
| GET | /api/currencies | Currency |
| GET | /api/rates/history | Charts |
| GET | /api/rates/previous | Previous UTC day |
| POST | /api/convert | Converter |
/v1 provides a compact query API. /api supplies the website’s latest-rate, history and conversion contracts. Their defaults and response shapes differ; do not interchange them.
GET /v1/currencies
All symbols with current rates, with provider names. Includes available alternatives and metals.
Parameter: —
curl --request GET 'https://lumeexchangerates.com/v1/currencies'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"mode": "provider",
"source": "External exchange-rate provider",
"source_url": "https://openexchangerates.org/",
"as_of": "2026-01-01T00:00:00.000Z",
"fetched_at": "2026-01-01T00:00:05.000Z",
"currency_count": 3,
"includes_alternative": true,
"refresh_interval_seconds": 300,
"provider_plan": "Unlimited",
"notice": "Illustrative response; not live rates."
},
"data": [
{
"code": "USD",
"name": "United States Dollar"
},
{
"code": "EUR",
"name": "Euro"
},
{
"code": "JPY",
"name": "Japanese Yen"
}
]
}| Parameter | Type | Description |
|---|---|---|
| data[].code | string | Uppercase symbol. Alternative assets can exceed three characters or include underscores. |
| data[].name | string | Provider name, or the code itself when no name is available. |
GET /v1/quotes
Base symbol; defaults to USD. Any current provider symbol is accepted.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| anchor | string | Optional | USD | Base symbol; defaults to USD. Any current provider symbol is accepted. |
| targets | string | Optional | all | Comma-separated target symbols. Omit to return all available symbols. |
curl --request GET 'https://lumeexchangerates.com/v1/quotes?anchor=USD&targets=EUR,JPY'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"mode": "provider",
"source": "External exchange-rate provider",
"source_url": "https://openexchangerates.org/",
"as_of": "2026-01-01T00:00:00.000Z",
"fetched_at": "2026-01-01T00:00:05.000Z",
"currency_count": 3,
"includes_alternative": true,
"refresh_interval_seconds": 300,
"provider_plan": "Unlimited",
"notice": "Illustrative response; not live rates."
},
"anchor": "USD",
"data": [
{
"currency": "EUR",
"value": 0.9
},
{
"currency": "JPY",
"value": 150
}
]
}Example: /v1/quotes?anchor=EUR&targets=USD,JPY. value is target units per one anchor unit. Duplicate targets are removed. Empty, lowercase or unavailable symbols return 400.
| Parameter | Type | Description |
|---|---|---|
| anchor | string | Base symbol; defaults to USD. Any current provider symbol is accepted. |
| data[].currency | string | To |
| data[].value | number | rates[currency] / rates[anchor] |
GET /v1/exchange
Non-negative numeric amount to convert.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| from | string | Optional | USD | Source currency symbol; defaults to USD. |
| to | string | Optional | KRW | Target currency symbol; defaults to KRW. |
| quantity | number | Optional | 1 | Non-negative numeric amount to convert. |
curl --request GET 'https://lumeexchangerates.com/v1/exchange?from=USD&to=EUR&quantity=100'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"mode": "provider",
"source": "External exchange-rate provider",
"source_url": "https://openexchangerates.org/",
"as_of": "2026-01-01T00:00:00.000Z",
"fetched_at": "2026-01-01T00:00:05.000Z",
"currency_count": 3,
"includes_alternative": true,
"refresh_interval_seconds": 300,
"provider_plan": "Unlimited",
"notice": "Illustrative response; not live rates."
},
"data": {
"from": "USD",
"to": "EUR",
"quantity": 100,
"rate": 0.9,
"result": 90
}
}Example: /v1/exchange?from=USD&to=EUR&quantity=100. Always specify from and to in global integrations. This legacy GET route defaults to KRW. Empty values, negatives, NaN, infinity and result overflow return 400.
| Parameter | Type | Description |
|---|---|---|
| data.rate | number | rates[to] / rates[from] |
| data.result | number | quantity × rate |
GET /api/rates/latest
Latest published rate
Parameter: —
curl --request GET 'https://lumeexchangerates.com/api/rates/latest'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"provider": "External exchange-rate provider",
"kind": "latest_published",
"provider_timestamp": 1767225600,
"published_at": "2026-01-01T00:00:00.000Z",
"expected_interval_seconds": 300,
"lag_seconds": 5,
"stale": false,
"timezone": "Asia/Seoul",
"fetched_at": "2026-01-01T00:00:05.000Z",
"persistent_storage": false
},
"data": {
"base": "USD",
"rates": {
"USD": 1,
"EUR": 0.9,
"JPY": 150
}
}
}| Parameter | Type | Description |
|---|---|---|
| data.base | string | USD |
| data.rates | object | All available USD-relative rates; validate availability against the latest response. |
| meta.provider_timestamp | integer | UTC · UNIX seconds |
| meta.published_at | string | ISO 8601 · UTC |
| meta.fetched_at | string | Server retrieval time, distinct from provider publication time. |
| meta.expected_interval_seconds | integer | seconds |
| meta.stale | boolean | True when age exceeds max(3 × expected interval, 900 seconds). |
| meta.lag_seconds | integer | Seconds since provider publication. |
| meta.persistent_storage | boolean | Whether the persistent collection service is connected. |
| meta.kind | string | latest_published | utc_daily |
GET /api/currencies
Currency
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| lang | string | Optional | en | en / ko / ja / zh / es / hi / bn / de / fr / nl / pt / it / ru / vi / th / ar / id / ur |
curl --request GET 'https://lumeexchangerates.com/api/currencies?lang=en'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"provider": "External exchange-rate provider",
"kind": "latest_published",
"provider_timestamp": 1767225600,
"published_at": "2026-01-01T00:00:00.000Z",
"expected_interval_seconds": 300,
"lag_seconds": 5,
"stale": false,
"timezone": "Asia/Seoul",
"fetched_at": "2026-01-01T00:00:05.000Z",
"persistent_storage": false
},
"data": [
{
"code": "USD",
"name": "US Dollar"
},
{
"code": "EUR",
"name": "Euro"
}
]
}Currency names use Intl.DisplayNames. Unrecognized assets retain their codes. Only symbols present in the latest data are returned.
GET /api/rates/history
Daily history and date-range series are available through /v1/history and /v1/series.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| from | string | Optional | USD | From |
| to | string | Optional | EUR | To |
| period | enum | Optional | 1M | 1D | 1W | 1M | 3M | 1Y |
curl --request GET 'https://lumeexchangerates.com/api/rates/history?from=USD&to=EUR&period=1W'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"kind": "utc_daily",
"from": "USD",
"to": "EUR",
"period": "1W",
"provider": "External exchange-rate provider",
"persistent_storage": false
},
"data": [
{
"time": "2026-01-01",
"value": 0.9
},
{
"time": "2026-01-02",
"value": 0.91
}
]
}1W starts seven days ago; 1M, 3M and 1Y use calendar periods. All daily ranges end yesterday, excluding the unfinished current UTC day. Month-end and leap-year boundaries are clamped. Longer ranges are split by calendar month, merged chronologically and deduplicated.
| Parameter | Type | Description |
|---|---|---|
| data[].time | string | integer | Daily: YYYY-MM-DD (UTC). Intraday: UNIX seconds. |
| data[].value | number | rates[to] / rates[from] |
| meta.kind | string | utc_daily | intraday |
{
"meta": {
"kind": "intraday",
"persistent_storage": false
},
"data": []
}Without the collection service, 1D returns HTTP 200 and an empty data array as above. This is not fabricated minute data or an error. Symbols unavailable in a historical period can fail lookup.
GET /api/rates/previous
Previous UTC day
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| from | string | Optional | USD | From |
| to | string | Optional | EUR | To |
curl --request GET 'https://lumeexchangerates.com/api/rates/previous?from=USD&to=EUR'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"kind": "utc_daily",
"reference_date": "2026-01-01",
"reference_timestamp": "2026-01-01T23:59:59Z"
},
"data": {
"from": "USD",
"to": "EUR",
"rate": 0.9,
"rates": {
"USD": 1,
"EUR": 0.9
}
}
}The comparison uses the previous UTC day’s provider reference. reference_timestamp is the logical day-end boundary, not a quote’s actual publication time. Percentage change is (current − reference) / reference × 100.
POST /api/convert
Converter
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Content-Type | header | Required | application/json | application/json |
| amount | number | Required | — | 0 ≤ amount ≤ 1e15; finite |
| from | string | Required | — | From |
| to | string | Required | — | To |
curl --request POST 'https://lumeexchangerates.com/api/convert' \
--header 'Content-Type: application/json' \
--data '{"amount":100,"from":"USD","to":"EUR"}'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"provider": "External exchange-rate provider",
"kind": "latest_published",
"provider_timestamp": 1767225600,
"published_at": "2026-01-01T00:00:00.000Z",
"expected_interval_seconds": 300,
"lag_seconds": 5,
"stale": false,
"timezone": "Asia/Seoul",
"fetched_at": "2026-01-01T00:00:05.000Z",
"persistent_storage": false
},
"data": {
"amount": 100,
"from": "USD",
"to": "EUR",
"rate": 0.9,
"result": 90
}
}Send amount as a JSON number: "100" as a string returns 400. Symbols must exist in the latest snapshot. This endpoint calculates a value; it does not execute a transfer or trade.
GET /v1/history
Daily history and date-range series are available through /v1/history and /v1/series.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| date | YYYY-MM-DD | Required | — | 1999-01-01 ≤ date ≤ UTC today |
| anchor | string | Optional | USD | From |
| targets | CSV | Optional | all | To |
curl --request GET 'https://lumeexchangerates.com/v1/history?date=2026-01-01&anchor=EUR&targets=USD,JPY'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"date": "2026-01-01",
"published_at": "2026-01-01T23:00:00Z",
"partial_day": false
},
"anchor": "EUR",
"data": [
{
"currency": "USD",
"value": 1.1
}
]
}| Parameter | Type | Description |
|---|---|---|
| meta.partial_day | boolean | UTC daily reference |
| meta.published_at | ISO 8601 UTC | Latest published rate |
GET /v1/series
Daily history and date-range series are available through /v1/history and /v1/series.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| start / end | YYYY-MM-DD | Required | — | 1999-01-01 ≤ start ≤ end < UTC today; ≤ 366 days inclusive |
| anchor / targets | string / CSV | Optional | USD / all | same as /v1/quotes |
curl --request GET 'https://lumeexchangerates.com/v1/series?start=2026-01-01&end=2026-01-07&anchor=USD&targets=EUR'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"start": "2026-01-01",
"end": "2026-01-02",
"timezone": "UTC",
"count": 2
},
"anchor": "USD",
"data": [
{
"date": "2026-01-01",
"rates": [
{
"currency": "EUR",
"value": 0.9
}
]
},
{
"date": "2026-01-02",
"rates": [
{
"currency": "EUR",
"value": 0.91
}
]
}
]
}OHLC via /v1/candles requires provider entitlement. Check /v1/capabilities; availability follows the configured plan.
{
"timezone": "UTC",
"date_bounds": "inclusive",
"max_days": 366,
"upstream_chunk": "calendar_month"
}GET /v1/candles
OHLC via /v1/candles requires provider entitlement. Check /v1/capabilities; availability follows the configured plan.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| start | YYYY-MM-DDTHH:mm:00Z | Required | — | UTC; completed period only; ≥ 2016-12-19 |
| period | enum | Required | — | 1m | 5m | 15m | 30m | 1h | 12h | 1d | 1w | 1mo |
| anchor / targets | string / CSV | Optional | USD / all | provider base / symbols |
curl --request GET 'https://lumeexchangerates.com/v1/candles?start=2026-01-01T00%3A00%3A00Z&period=1d&anchor=USD&targets=EUR'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"meta": {
"start": "2026-01-01T00:00:00Z",
"end": "2026-01-01T23:59:59Z",
"period": "1d"
},
"anchor": "USD",
"data": [
{
"currency": "EUR",
"open": 0.9,
"high": 0.92,
"low": 0.89,
"close": 0.91,
"average": 0.905
}
]
}{
"source": "provider_ohlc",
"synthetic": false,
"cross_rate_ohlc": false,
"max_age": {
"1m": "1h",
"5m": "24h",
"15m": "24h",
"30m": "32d",
"1h": "32d"
},
"alignment_minutes": {
"5m": 5,
"15m": 15,
"30m": 30,
"1h": 30,
"12h": 30,
"1d": 30
},
"calendar_alignment": {
"1w": "00:00 UTC",
"1mo": "YYYY-MM-01T00:00:00Z"
}
}GET /v1/capabilities
Availability
Parameter: —
curl --request GET 'https://lumeexchangerates.com/v1/capabilities'The values and dates below illustrate response structure; they are not live rates. Arrays may show only a subset. Use the API explorer for current data.
{
"data": {
"latest": true,
"currencies": true,
"conversion": "latest_snapshot",
"historical": "verified_on_request",
"time_series": true,
"ohlc": false,
"refresh_interval_seconds": 300,
"customer_api_keys": false
}
}OHLC via /v1/candles requires provider entitlement. Check /v1/capabilities; availability follows the configured plan.
Data & precision
An exchange rate is useful only when its meaning is clear. Our rates are indicative references, not a bank offer or a guaranteed transaction price. Currency conversion uses a shared rate snapshot; rounding belongs at the display or settlement stage.
rate = rates[to] / rates[from]
result = amount * rateRates preserve floating-point precision without fixed decimal truncation. Round only for display or your accounting policy.
All rates use one source unit, including JPY. Multiply by 100 only at the display layer if needed. Account for JavaScript binary floating-point error and apply an explicit decimal and rounding policy for settlement.
Timestamps
UNIX timestamps are UTC seconds and ISO timestamps use Z. Daily UTC dates may differ from local calendar dates. The website displays latest publication time in the browser’s timezone. meta.timezone is a server display hint; it does not alter timestamp semantics.
| Parameter | Type | Description |
|---|---|---|
| /v1 meta.as_of | ISO 8601 | YYYY-MM-DD | Provider timestamp |
| /v1 meta.refresh_interval_seconds | integer | Cache |
| /v1 meta.currency_count | integer | … currencies available |
| /v1 meta.mode | provider | daily | Data source |
| /api meta.published_at | ISO 8601 UTC | Latest published rate |
| history data[].time | YYYY-MM-DD UTC | UNIX seconds | UTC daily reference |
Errors
| HTTP | code | Description |
|---|---|---|
| 400 | INVALID_CURRENCY / INVALID_INPUT / INVALID_CONVERSION / INVALID_JSON / INVALID_PERIOD | Enter a non-negative amount |
| 405 | METHOD_NOT_ALLOWED | GET: /v1/*, /api/rates/*, /api/currencies; POST: /api/convert |
| 404 | NOT_FOUND | /api/rates/* |
| 422 | HISTORY_NOT_IN_PLAN / DATA_UNAVAILABLE | Availability |
| 429 | RATE_LIMITED | /api/* · 90 / IP / minute |
| 404 | NOT_FOUND | Unknown /v1 endpoint |
| 422 | FEATURE_NOT_IN_PLAN / HISTORY_NOT_IN_PLAN / OHLC_NOT_IN_PLAN | Availability |
| 400 | INVALID_DATE / INVALID_DATE_RANGE / INVALID_PERIOD / INCOMPLETE_PERIOD | Enter a non-negative amount |
| 503 | PROVIDER_UNAVAILABLE / DATA_UNAVAILABLE / SERVICE_UNAVAILABLE | Rates are unavailable. Please try again shortly. |
{
"error": {
"code": "INVALID_CURRENCY",
"message": "Symbol not available in latest provider data"
}
}message can be omitted. Branch on HTTP status and error.code. Correct invalid input before retrying. For 429 or transient 503, use bounded exponential backoff with jitter. Retry-After is not currently guaranteed.
Limits & caching
Latest data is cached rather than fetched again for every keystroke. The configured feed currently targets five-minute updates. The /api routes allow 90 requests per minute per client IP; the direct Worker limit is isolate-local, while a connected Redis service enforces it across instances. /v1 does not currently enforce the advertised future plan quotas.
Responses use Cache-Control: no-store. Browser response caching differs from the server’s provider cache. Reuse snapshots by publication time in your application. An available last-good snapshot can be returned during provider outages: inspect stale or as_of. Direct Worker caches are not persistent storage.
{
"endpoints": [
"/v1/history",
"/v1/series",
"/v1/candles",
"/v1/capabilities"
],
"requests_per_ip_per_minute": 60,
"cache": "in_process",
"completed_history_cache_seconds": 3600,
"current_day_cache_seconds": 60
}Availability
OHLC via /v1/candles requires provider entitlement. Check /v1/capabilities; availability follows the configured plan.
OHLC via /v1/candles requires provider entitlement. Check /v1/capabilities; availability follows the configured plan.
API explorer
Call the API on this site. Your provider key stays on the server.
Run the request to view the real JSON response.