Appearance
FX Rates API
The FX Rates API exposes the current foreign exchange rates used by the Fyralynx EPC normalisation engine. All 23 supported currencies are expressed relative to USD as the base. The response includes a staleness flag and age-in-hours so your integration can detect when rates are approaching the refresh threshold.
Base path: https://api.fyralynx.com/v1
Tier required: Publisher or Enterprise
Why FX Rates Matter
The Fyralynx EPC scoring formula normalises all affiliate earnings to USD for ranking:
normalized_epc_usd = epc_local × fx_rate(local_currency → USD)When a merchant profile declares an EPC hint in INR (e.g. epcHints.Cuelinks = 0.030 for Amazon IN), the formula converts it to USD using the live fx_rates.INR value before comparing it against, say, a USD-denominated Amazon US EPC hint.
If FX data is older than 36 hours, the routing engine applies a confidence penalty of −0.02 to all scored routes in that decision. This is visible in CRC traces as:
json
{ "name": "fx", "value": 1.0, "label": "FX data stale (>36h) - confidence penalty applied", "source": "essential" }Integrations that build their own EPC calculations on top of this API should apply the same staleness logic.
The FX Rates Object
json
{
"base": "USD",
"timestamp": "2026-05-16T00:05:23Z",
"ageHours": 8.3,
"isStale": false,
"staleBeyondHours": 36,
"confidencePenalty": 0.0,
"source": "exchangerate.host",
"rates": {
"USD": 1.000000,
"GBP": 0.785412,
"EUR": 0.921034,
"INR": 83.452100,
"CAD": 1.362800,
"AUD": 1.534900,
"JPY": 155.720000,
"SGD": 1.345600,
"MYR": 4.712300,
"THB": 36.450000,
"IDR": 15842.000000,
"PHP": 56.230000,
"AED": 3.672500,
"SAR": 3.750400,
"EGP": 47.850000,
"NGN": 1542.000000,
"ZAR": 18.620000,
"BRL": 5.124000,
"MXN": 17.230000,
"ARS": 897.500000,
"KRW": 1348.200000,
"TWD": 32.150000,
"VND": 25400.000000
}
}Field reference
| Field | Type | Description |
|---|---|---|
base | string | Always "USD". All rates are expressed as units of the named currency per 1 USD. |
timestamp | string (ISO 8601) | When the rates were last fetched from the upstream source. |
ageHours | number | Hours elapsed since timestamp. |
isStale | boolean | true when ageHours > staleBeyondHours. Confidence penalty is active. |
staleBeyondHours | number | Threshold in hours. Currently 36. |
confidencePenalty | number | −0.02 when stale; 0.0 when fresh. Applied to all EPC scores when non-zero. |
source | string | Upstream data source: exchangerate.host or open.er-api.com (fallback). |
rates | object | Map of ISO 4217 currency code → exchange rate (units per USD). |
GET /fx-rates - Get current FX rates
Returns the current exchange rates in use by the EPC normalisation engine.
Tier: Publisher+
Cache behaviour: Rates are refreshed once daily at 00:05 UTC via a Cloudflare Cron Trigger. The API response is not additionally cached - it reads directly from Cloudflare KV and always reflects the most recent refresh.
Response - 200 OK
Full FX rates object as shown above.
curl example
bash
curl "https://api.fyralynx.com/v1/fx-rates" \
-H "Authorization: Bearer $FYRALYNX_API_KEY"TypeScript example
typescript
interface FxRates {
base: 'USD';
timestamp: string;
ageHours: number;
isStale: boolean;
staleBeyondHours: number;
confidencePenalty: number;
source: string;
rates: Record<string, number>;
}
async function getFxRates(): Promise<FxRates> {
const response = await fetch('https://api.fyralynx.com/v1/fx-rates', {
headers: {
Authorization: `Bearer ${process.env.FYRALYNX_API_KEY}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Fyralynx ${response.status}: ${error.code}`);
}
const { data } = await response.json();
return data;
}Python example
python
import httpx
def get_fx_rates() -> dict:
response = httpx.get(
"https://api.fyralynx.com/v1/fx-rates",
headers={"Authorization": f"Bearer {FYRALYNX_API_KEY}"},
)
response.raise_for_status()
return response.json()["data"]Currency Conversion Utilities
If you're building your own EPC calculations, these helpers show how to apply the FX data:
Convert local EPC to USD
typescript
function epcToUsd(epcLocal: number, currency: string, rates: FxRates): number {
if (currency === 'USD') return epcLocal;
const rate = rates.rates[currency];
if (rate === undefined || rate === 0) {
throw new Error(`Unsupported or zero rate for currency: ${currency}`);
}
// rates[currency] = units of currency per 1 USD
// So 1 INR = 1/83.45 USD
return epcLocal / rate;
}
// Example: Amazon IN via Cuelinks, EPC = 0.030 INR
const epcUsd = epcToUsd(0.030, 'INR', fxRates);
// → 0.000359 USDConvert USD EPC to creator's display currency
typescript
function epcToDisplay(
epcUsd: number,
displayCurrency: string,
rates: FxRates,
): number {
if (displayCurrency === 'USD') return epcUsd;
const rate = rates.rates[displayCurrency];
if (rate === undefined) {
throw new Error(`Unsupported currency: ${displayCurrency}`);
}
return epcUsd * rate;
}
// Convert $0.043 USD to GBP for a UK creator
const epcGbp = epcToDisplay(0.043, 'GBP', fxRates);
// → 0.0338 GBPApply staleness confidence penalty
typescript
function applyStalenessPenalty(score: number, fxRates: FxRates): number {
return score * (1 + fxRates.confidencePenalty);
// confidencePenalty is -0.02 when stale, 0.0 when fresh
}Supported Currencies
All 23 currencies supported by the Fyralynx EPC engine:
| Code | Currency | Region |
|---|---|---|
USD | US Dollar | United States |
GBP | British Pound | United Kingdom |
EUR | Euro | Eurozone |
INR | Indian Rupee | India |
CAD | Canadian Dollar | Canada |
AUD | Australian Dollar | Australia |
JPY | Japanese Yen | Japan |
SGD | Singapore Dollar | Singapore |
MYR | Malaysian Ringgit | Malaysia |
THB | Thai Baht | Thailand |
IDR | Indonesian Rupiah | Indonesia |
PHP | Philippine Peso | Philippines |
AED | UAE Dirham | United Arab Emirates |
SAR | Saudi Riyal | Saudi Arabia |
EGP | Egyptian Pound | Egypt |
NGN | Nigerian Naira | Nigeria |
ZAR | South African Rand | South Africa |
BRL | Brazilian Real | Brazil |
MXN | Mexican Peso | Mexico |
ARS | Argentine Peso | Argentina |
KRW | South Korean Won | South Korea |
TWD | New Taiwan Dollar | Taiwan |
VND | Vietnamese Dong | Vietnam |
FX Pipeline Architecture
Understanding how rates are generated helps you reason about freshness:
Data sources
- Primary:
exchangerate.host- free-tier API, no API key required. Provides daily rates for all 23 supported currencies. - Fallback:
open.er-api.com- activated automatically if the primary source fails or returns incomplete data.
If both sources fail, the previous rates are retained in Cloudflare KV. The staleness threshold applies in this case - if rates are > 36 hours old, all routing decisions carry the −0.02 confidence penalty.
Refresh schedule
The fx-refresh Cloudflare Cron Worker runs at 00:05 UTC daily. The 5-minute offset from midnight avoids competing with other high-traffic cron jobs and gives source APIs time to publish the new day's rates.
KV key
FX rates are stored under the key fx_rates in the FYRALYNX_CONFIG KV namespace as:
json
{
"base": "USD",
"rates": { "INR": 83.45, "GBP": 0.785, … },
"timestamp": "2026-05-16T00:05:23Z",
"source": "exchangerate.host"
}The API adds ageHours, isStale, staleBeyondHours, and confidencePenalty computed fields before returning.
Monitoring Staleness in Your Integration
If you use FX rates from this API in your own EPC calculations, implement a staleness check:
typescript
async function getFxRatesWithStalenessCheck(): Promise<FxRates> {
const rates = await getFxRates();
if (rates.isStale) {
console.warn(
`Fyralynx FX rates are stale (age: ${rates.ageHours.toFixed(1)}h). ` +
`A confidence penalty of ${rates.confidencePenalty} is active. ` +
`Rates will refresh at the next scheduled run (00:05 UTC).`
);
}
if (rates.ageHours > 72) {
// Extremely stale - something is wrong with the refresh cron
throw new Error(`FX rates are ${rates.ageHours.toFixed(1)}h old. Check Fyralynx status.`);
}
return rates;
}You can also monitor the Fyralynx status page for FX refresh failures.
Error Reference
| Code | Status | Description |
|---|---|---|
PUBLISHER_TIER_REQUIRED | 403 | API access requires Publisher or Enterprise plan. |
RATE_LIMIT_EXCEEDED | 429 | Rate limit exceeded. |
INTERNAL_SERVER_ERROR | 500 | Unexpected error reading FX data from KV. Rates are not corrupted - retry. |
See Also
- API Overview - base URL, authentication, error format
- Merchants API - EPC hints (denominated in local currency, converted via these rates)
- Concepts: EPC Model -
fxsignal and its role in the scoring formula - Webhooks -
commission_rate.changedevents (related: network rate changes that affect EPC hints) - Fyralynx Status Page - FX refresh job uptime monitoring