# Migrate from Fixer

> Move a Fixer integration to CurrencyCore: access_key to bearer auth, latest and convert mapping, timeseries to history, response fields, pricing differences, and caveats.

Canonical: https://currency-core.com/docs/guides/migrate-fixer/
Updated: 2026-11-11
Published: 2026-11-11

---
Fixer is a commercial FX API with a familiar `latest` and `convert` shape. Most
of the integration survives a move to CurrencyCore because the ISO codes and the
"units per one unit of base" arithmetic stay the same. The auth model, the
default base, the history packaging, and the error envelope do not.

Public Fixer pricing and coverage below were checked on **2026-11-10**. Verify
the vendor's current plan before you budget.

## What changes at a glance

| Area | Fixer | CurrencyCore |
|---|---|---|
| Currencies | 170 currencies | 160 fiat currencies |
| History | 1999 onward | GBP/USD and USD/INR parity from 1949, daily majors from 1971, EUR pairs from 1999 |
| Free quota | 100 calls/mo, non-commercial | 1,000 requests/mo, 60/min, test keys |
| Entry paid plan | Basic, $14.99/mo | Starter, $9/mo, full history |
| Update cadence | Hourly on Free and Basic, faster on higher tiers, 60 seconds on Pro Plus | Central-bank reference rates polled hourly, daily fixings |
| Auth | `access_key` query parameter | `Authorization: Bearer` or `x-api-key` |
| Default base | EUR | USD on `/v1/rates`, any base on `/v1/rates/{base}` |

CurrencyCore does not sell a 60-second executable quote. If the Pro Plus cadence
is a product requirement, Fixer remains the better fit. CurrencyCore is for
reference rates, longer history, PPP, and analytics.

## 1. Replace access_key with a bearer token

Fixer samples pass the key in the query string:

```bash
curl "https://data.fixer.io/api/latest?access_key=YOUR_KEY&base=USD&symbols=EUR,INR"
```

CurrencyCore uses a header:

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

Remove `access_key` from URLs, logs, fixtures, and browser history. Do not keep
query-string auth as a fallback in staging: dual auth doubles the places a key
can leak. Use a test key on Free while integrating, then a live key on a paid
plan. See [Authentication](/docs/authentication/).

## 2. Map endpoints

| Fixer endpoint | CurrencyCore endpoint | Mapping note |
|---|---|---|
| `/latest?base=USD&symbols=EUR,INR` | `/v1/rates/USD` | Base moves to the path. Filter the `rates` map locally. |
| `/latest` with the default EUR base | `/v1/rates/EUR` | `/v1/rates` is USD only. |
| `/{date}` | `/v1/rates/{base}?date=YYYY-MM-DD` | Fixer takes the date as the path; use `/v1/convert?date=` for a dated amount. |
| `/convert?from=USD&to=INR&amount=100` | `/v1/convert?from=USD&to=INR&amount=100` | Read `results[0].result`. |
| `/timeseries?start_date=&end_date=` | `/v1/history?currency=EUR&from=&to=` | One currency per call. |
| `/fluctuation?start_date=&end_date=` | `/v1/history/analysis` | Requires Growth or higher. Not a field-for-field match. |
| `/symbols` | `/v1/currencies` | Public endpoint with metadata, not only a code map. |

The Fixer `symbols` filter has no direct CurrencyCore parameter. `/v1/rates/USD`
returns the full snapshot; read the codes you need from `rates` and cache the
response. That trades a larger payload for one fewer per-call parameter.

## 3. Map response fields

A Fixer latest response looks like this:

```json
{
  "success": true,
  "timestamp": 1762732800,
  "base": "EUR",
  "date": "2026-11-10",
  "rates": { "USD": 1.0861, "INR": 91.62 }
}
```

The CurrencyCore equivalent for the same base is:

```json
{
  "base": "EUR",
  "date": "2026-11-10",
  "rates": { "EUR": 1, "USD": 1.0861, "INR": 91.62 }
}
```

`base`, `date`, and `rates` map directly. The `success` flag has no equivalent:
CurrencyCore returns HTTP `200` on success and an HTTP status plus an error
envelope on failure. Read the status first, then `error.code` if present.

A Fixer conversion:

```json
{ "success": true, "result": 108.61 }
```

becomes:

```json
{ "from": "USD", "amount": 100, "date": "2026-11-10", "results": [{ "to": "INR", "result": 9162, "rate": 91.62 }] }
```

The converted amount is `results[0].result`. The rate is `results[0].rate`. If
you send several targets, match by `results[].to`.

A Fixer timeseries keyed by date:

```json
{ "success": true, "start_date": "2026-11-09", "end_date": "2026-11-10", "rates": { "2026-11-09": { "INR": 91.5 }, "2026-11-10": { "INR": 91.62 } } }
```

becomes a dense CurrencyCore series:

```json
{ "currency": "INR", "base": "USD", "from": "2026-11-09", "to": "2026-11-10", "rates": { "2026-11-09": 91.5, "2026-11-10": 91.62 } }
```

CurrencyCore includes weekends and holidays by carrying the previous rate
forward. Provider series that omit non-trading days need a filter in your adapter
if your chart depends on gaps.

| Fixer field | CurrencyCore field | Note |
|---|---|---|
| `base` | `base` | Use `/v1/rates/{base}` for a non-USD base |
| `date` | `date` | UTC calendar date |
| `timestamp` | none | Use `date`; the API does not return an epoch |
| `rates` | `rates` | Values are units per 1 base |
| `result` | `results[0].result` | Conversion is an array |
| `start_date` and `end_date` | `from` and `to` | Inclusive UTC dates |
| `success` | HTTP status | Errors use `{ "error": { "code", "message" } }` |

See [Errors](/docs/errors/) for status codes and retry behavior.

## 4. Plan for the coverage differences

Fixer advertises **170 currencies** and history from **1999**. CurrencyCore
advertises **160 fiat currencies**, with deeper history on a narrower set of
pairs. The practical checks:

- Run a code diff between your Fixer usage and `/v1/currencies`. Do not assume
  every Fixer code is quoted by CurrencyCore.
- CurrencyCore does not quote metals or crypto. If your Fixer usage includes
  those instruments, keep a separate provider.
- Free is limited to the **last 30 days** of history even though the dataset
  reaches 1949. Starter and above get full history.
- "History from 1949" is not a promise of daily data for every pair. It is annual
  parity for GBP/USD and USD/INR, daily majors from 1971, and EUR pairs from
  1999. See [History coverage](/docs/guides/history-coverage/) and the
  [`/history` reference](/docs/history-endpoint/).

Fixer's Basic plan is **$14.99/mo** for 10,000 calls and hourly updates, with
**60-second updates on Pro Plus**. CurrencyCore starts at **$9/mo** for 50,000
requests and full history, but it does not offer a 60-second cadence. Compare
the plan features you actually need rather than the headline request count.

## 5. Cut over

1. Create a CurrencyCore organization and a test key.
2. Replace `access_key` with the bearer header in one client module.
3. Rewrite `/latest` calls as `/v1/rates/{base}` and delete the `symbols`
   parameter in favor of local filtering.
4. Rewrite `/convert` calls and read `results[0]`.
5. Rewrite `/timeseries` calls as `/v1/history`, one currency at a time.
6. Shadow a sample of production requests and compare the same fixing dates.
7. Switch reads, watch `401`, `403`, and `429`, then revoke the Fixer key.
8. Keep the old adapter until the next billing cycle in case rollback is needed.

For the provider-neutral version of this checklist, see
[Migrate an existing integration](/docs/guides/migration/).

## Related

- [Migration overview](/docs/guides/migration/)
- [OpenAPI specification](/docs/openapi/)
- [Authentication](/docs/authentication/)
- [Errors](/docs/errors/)
- [Rate limits](/docs/rate-limits/)
- [All integration guides](/docs/guides/)
- [`/rates` endpoint](/docs/rates-endpoint/)
- [`/convert` endpoint](/docs/convert-endpoint/)
- [`/history` endpoint](/docs/history-endpoint/)
