Integrations

Migrate an Existing Currency API Integration

Move a currency API integration to CurrencyCore: plan choice, bearer auth, currency and history coverage, response mapping, endpoint mapping, and a cutover checklist.


This guide is the provider-neutral path. It covers the decisions that apply whichever currency API you are leaving: which plan to start on, how authentication changes, what currency and history coverage you actually get, how to map response fields, and how to cut over without guessing.

Provider-specific mappings are in the Fixer guide, the CurrencyLayer guide, and the ExchangeRate-API guide. All integration guides are listed under Guides.

CurrencyCore is not a drop-in replacement at the wire level. The host, the auth header, the response envelope, and in some cases the base-currency semantics change. The ISO codes and the arithmetic do not. Plan for response mapping and a comparison pass, not only a host swap.

Provider-specific mappings

Each provider guide covers the same six areas: auth, base semantics, response shape, history, errors and cutover. Start with the one you are leaving.

ProviderAuth styleMain response shapeWhat changes mostGuide
Fixeraccess_key query parameterlatest and convert objectsMove the key to a bearer header and map the result envelopeFixer
CurrencyLayeraccess_key query parameterquotes keyed by concatenated pairStrip the base prefix and map to ratesCurrencyLayer
ExchangeRate-APIkey in the URL pathconversion_rates mapMove the key out of the URL and drop the status envelopeExchangeRate-API
Open Exchange Ratesapp_id query parameterrates map with an epoch timestampUse header auth and a UTC calendar dateOpen Exchange Rates
currencyapi.comapikey header or querydata wrapperUnwrap data and use a bearer headercurrencyapi.com
Frankfurterkeylessrates mapAdd auth, a base path and plan limitsFrankfurter

If your provider is not listed, use the provider-neutral mapping below. The decisions are the same.

1. Choose the entry plan

Public CurrencyCore pricing was checked on 2026-11-10.

StagePlanWhat it includesMain limits
EvaluationFree, $01,000 requests per month, 100 AI credits, 3 seats60 requests/min, last 30 days of history, test keys only
Production entryStarter, $9/mo50,000 requests per month, full history, live keys, 10 seats120 requests/min, no analytics endpoints
Analytics and BYOKGrowth, $29/mo500,000 requests per month, analytics endpoints, BYOK600 requests/min
High volumeBusiness, $199/mo10,000,000 requests per month, SSO and audit logs6,000 requests/min

Use Free to verify codes and response shapes. Use Starter when the integration needs live keys or history older than 30 days. Use Growth only when you need /v1/history/analysis, /v1/volatility, /v1/correlation, /v1/drawdown, /v1/safe-haven, /v1/mean-reversion, or /v1/ppp/analysis. See Rate limits and plan quotas for the full table.

2. Move authentication out of the URL

Many providers take a key as a query parameter named access_key, apikey, or key. CurrencyCore takes a header:

curl "https://api.currency-core.com/v1/rates/USD" \
  -H "Authorization: Bearer cc_live_your_key"

x-api-key: cc_live_your_key is equivalent. There is no query-string authentication. Remove the old query parameter from code, fixtures, logs, browser calls, and shared dashboards. A missing or invalid key returns 401 unauthorized.

Test keys use the cc_test_ prefix and always run at the Free per-minute limit. Live keys use cc_live_ and require a paid plan. Both count against the same organization quota. See Authentication for key creation, rotation, and environment behavior.

3. Diff the currency set before you switch

CurrencyCore quotes 160 fiat currencies. GET /v1/currencies returns 165 entries: the 160 fiat codes plus XAU, XAG, XPT, XPD, and XDR as reference entries. The rate feed is fiat only, so those five entries are not quoted rates.

Three practical consequences:

  • A provider that advertises more than 160 currencies may include metals, crypto, or regional codes that CurrencyCore does not quote. Check every code you store against /v1/currencies, not against the provider’s headline count.
  • There are no cryptocurrency rates. If your product prices BTC, ETH, or a stablecoin, keep a separate crypto provider.
  • Precious metals are not in the rate feed. If your product needs XAU or XAG, keep a metals provider or stay with a vendor that includes them.

Do the diff in code, not by reading a marketing page. Store the result in a fixture and fail a test if a required code disappears.

4. Understand history coverage and cadence

CurrencyCore history is not one uniform daily series from 1949. Coverage depends on the pair:

SeriesCoverage
GBP/USD and USD/INR annual parity1949
Daily major pairs1971
EUR pairs1999

Plan access is separate from data depth:

  • Free can request the last 30 days. Older dates return 403 forbidden.
  • Starter and above can request the full dataset.

The update model is also different from a tick feed. CurrencyCore uses central-bank reference rates, polled hourly, with daily fixings underneath. There is no real-time quote and no 60-second update guarantee. If your product needs executable sub-minute prices, CurrencyCore is the wrong feed. Dates are UTC calendar dates.

When a requested date has no snapshot, the API resolves to the most recent earlier one. date is the date actually used; requestedDate appears only when it differs. asOf lists currencies whose rate was carried forward. Your adapter should preserve those fields instead of inventing a fresh timestamp.

5. Map response shapes

The provider-neutral mapping is small, but it is not zero.

Rate snapshot

A snapshot with a rates map maps directly:

{ "base": "USD", "date": "2026-11-10", "rates": { "EUR": 0.9214, "INR": 84.07 } }

A provider that keys rates by concatenated pairs needs one transformation:

{ "source": "USD", "quotes": { "USDEUR": 0.9214, "USDINR": 84.07 } }

becomes rates.EUR and rates.INR when the base is USD. Strip the six-letter prefix, not a fixed three-letter chunk, so codes of different lengths do not break parsing.

Conversion

A single-result envelope becomes an array entry:

{ "result": 92.14, "rate": 0.9214 }

becomes:

{ "results": [{ "to": "EUR", "result": 92.14, "rate": 0.9214 }] }

Read results[0].result for the converted amount. Read results[0].rate for the rate. If you send multiple targets in to, match each result by to instead of assuming array position.

History

A provider that returns a map of dates to currency maps needs flattening:

{ "rates": { "2026-11-09": { "EUR": 0.92 }, "2026-11-10": { "EUR": 0.9214 } } }

becomes a dense date-to-rate map for one currency:

{ "currency": "EUR", "base": "USD", "rates": { "2026-11-09": 0.92, "2026-11-10": 0.9214 } }

CurrencyCore fills weekends and holidays by carrying the previous rate forward. That is deliberate. If your chart expects missing points, filter them in your adapter instead of treating the dense series as an error.

Field mapping

Common provider fieldCurrencyCore fieldNote
base or sourcebase/v1/rates is always USD; use /v1/rates/{base} for another base
date, timestamp, or time_last_update_utcdateCurrencyCore returns a UTC calendar date, not an epoch
ratesratesValues are units of the target per 1 unit of base
result or conversion_resultresults[0].resultConversion responses use an array
quotes.USDEURrates.EURStrip the base prefix
start_date and end_datefrom and toInclusive UTC dates
symbols or codes/v1/currenciesCurrencyCore returns metadata, not only a code list
success: trueHTTP 200CurrencyCore signals failure with an HTTP status and an error envelope

Errors are uniform:

{ "error": { "code": "unknown_currency", "message": "Currency code 'XYZ' is not recognized." } }

Read the stable code, not the message text. See Errors for the full catalog and retry guidance.

6. Map endpoints

Common provider endpointCurrencyCore endpointCaveat
Latest rates/v1/ratesUSD base only
Latest rates with another base/v1/rates/{base}Base moves from query to path
Convert an amount/v1/convertResponse uses results[], up to 25 targets
Dated snapshot/v1/rates/{base}?date=YYYY-MM-DDFree is limited to 30 days
Dated conversion/v1/convert?date=YYYY-MM-DDSame Free window
Time series/v1/historyOne currency per call, dense series
Change or fluctuation/v1/history/analysisGrowth or higher, and not a field-for-field match
Symbols or supported codes/v1/currenciesPublic, no key, no quota
Country reference/v1/countriesPublic, no key, no quota
PPP conversion/v1/convert?ppp=trueNo equivalent in most FX-only providers
Natural-language query/v1/aiSeparate AI credit pool

/v1/rates and /v1/convert cover the core migration. Everything else is optional and can be adopted later. The full parameter and response reference is at API reference and in the OpenAPI specification.

7. Cut over in a controlled order

  1. Inventory calls. List every provider endpoint, base currency, date range, and consumer. Mark which calls need history and which only need the latest snapshot.
  2. Create the key. Use a test key on Free for the first pass. Move to a live key only when the account is on a paid plan.
  3. Diff currencies. Compare every stored code with /v1/currencies. Decide what happens to unsupported codes before traffic moves.
  4. Write the adapter. Map auth, base currency, date fields, rates, results[], and the error envelope. Keep the old provider client behind the same interface so rollback is a switch, not a rewrite.
  5. Run shadow traffic. Send the same logical request to both providers. Do not compare timestamps literally; compare the rate for the same fixing date.
  6. Compare with tolerances. Allow for provider-specific rounding and for carry-forward dates. Investigate every gap beyond your tolerance instead of averaging it away.
  7. Switch reads. Move low-risk read paths first. Keep writes and billing calculations on the old provider until the comparison looks stable.
  8. Watch the right errors. 401 is auth, 402 is billing, 403 is a plan or date gate, and 429 is a quota or per-minute limit. Honor Retry-After.
  9. Revoke the old key. Do not leave dual auth in production. Rotate or revoke the provider key once the new path has served real traffic.
  10. Record rollback. Keep the old adapter and the last known good config until the next billing cycle, even after cutover.

Caveats to decide before you start

  • No metals or crypto quotes. The feed is fiat only.
  • No sub-minute feed. Reference rates are polled hourly; fixings are daily.
  • Base semantics differ. /v1/rates is USD. Use /v1/rates/{base} when your old provider defaulted to EUR or another base.
  • History is plan-gated. Free stops at 30 days even though the underlying dataset reaches 1949.
  • Quota accounting is not identical. Only HTTP 2xx responses count toward the monthly quota. The per-minute limit counts every request, including errors and retries. See Rate limits.
  • Analytics are not a rename. Provider “change” or “fluctuation” responses are not the same object as CurrencyCore’s analytics endpoints.

If these caveats are acceptable, the migration is mostly adapter work and comparison testing. If any of them is a hard product requirement, keep the provider that meets it instead of forcing an equivalence that does not exist.