Your database has a column called currency, and somewhere in it is HRK – a currency that no longer exists. Currency code changes happen every year: countries remove zeros after high inflation, launch new currencies or adopt the euro, and the ISO 4217 code changes with them. If your code treats currency lists as fixed, the next change will break a lookup, an invoice or a report.
A currency code change occurs when ISO 4217 assigns a new code because a currency is redenominated, replaced or withdrawn. In a redenomination, old units are swapped for new ones at a fixed ratio – for example 1,000 old Sierra Leonean leones (SLL) for 1 new leone (SLE). The old code remains valid for historical data.
Why currencies change codes
| Type of change | What happens | Example |
|---|---|---|
| Redenomination | Zeros removed; new unit = N old units | BYR → BYN (10,000:1) |
| Replacement by a new currency | New currency introduced, often at par | ANG → XCG (1:1) |
| Adoption of another currency | National currency replaced at a fixed conversion rate | HRK → EUR (7.53450:1) |
| Withdrawal / unification | One of two parallel currencies removed | CUC withdrawn in Cuba, 2021 |
The ISO 4217 maintenance agency, SIX, publishes each new code in List One and moves the old one to List Three (historic currencies). The old and new codes usually overlap for a transition period in which both are legal tender. For background on how the codes are built, see ISO 4217 currency codes.
Major code changes developers encounter
Dates and ratios as announced by the respective central banks, the ECB and ISO 4217 amendments.
| Old code | New code | Country / area | Effective | Ratio (old units per new unit) |
|---|---|---|---|---|
| ZMK | ZMW | Zambia | 1 Jan 2013 | 1,000 |
| LVL | EUR | Latvia | 1 Jan 2014 | 0.702804 |
| LTL | EUR | Lithuania | 1 Jan 2015 | 3.45280 |
| BYR | BYN | Belarus | 1 Jul 2016 | 10,000 |
| MRO | MRU | Mauritania | 1 Jan 2018 | 10 |
| STD | STN | São Tomé and Príncipe | 1 Jan 2018 | 1,000 |
| VEF | VES | Venezuela | 20 Aug 2018 | 100,000 |
| CUC | (CUP) | Cuba | 1 Jan 2021 | Withdrawn; holdings converted at 24 CUP per CUC |
| SLL | SLE | Sierra Leone | 1 Jul 2022 | 1,000 |
| HRK | EUR | Croatia | 1 Jan 2023 | 7.53450 |
| ZWL | ZWG | Zimbabwe | Apr 2024 | One-off conversion at 2,498.7242 ZWL per ZiG |
| ANG | XCG | Curaçao and Sint Maarten | 31 Mar 2025 | 1 (at par) |
The euro conversion rates are the fixed rates published by the European Central Bank.
Notes on individual changes
- Venezuela (VEF → VES, then VED). The sovereign bolívar replaced the bolívar fuerte on 20 August 2018 at 100,000:1. On 1 October 2021, six more zeros were removed (1,000,000:1) for the digital bolívar, which ISO 4217 lists as
VED. Before comparing Venezuelan rates across October 2021, check how your data source labels and adjusts the series. - Mauritania and São Tomé (2018). Both introduced new notes and coins on 1 January 2018. In São Tomé, old and new notes circulated together until 30 June 2018.
- Belarus (2016). Old and new rubles circulated in parallel from 1 July to 31 December 2016.
- Cuba (2021). Monetary unification started on 1 January 2021 with an official rate of 24 CUP per US dollar. The convertible peso (CUC) stopped being accepted in shops from 1 July 2021, and banks exchanged remaining CUC until 30 December 2021. CUC was withdrawn, not redenominated, so there is no successor code – the Cuban peso (CUP) continues.
- Sierra Leone (2022). New leones entered circulation on 1 July 2022; old and new notes circulated in parallel during a transition period that the Bank of Sierra Leone extended into 2023.
- Zimbabwe (2024). The Reserve Bank of Zimbabwe launched the ZiG (Zimbabwe Gold) in April 2024 and converted Zimbabwe dollar balances at 2,498.7242 ZWL per ZiG. ISO 4217 added the code
ZWGin June 2024, andZWLwas withdrawn on 1 September 2024. Unlike a redenomination, this was a new currency with a one-off conversion rate. - Curaçao and Sint Maarten (2025). The Caribbean guilder (XCG) replaced the Netherlands Antillean guilder (ANG) at par on 31 March 2025; ANG ceased to be legal tender on 1 July 2025. Both are pegged to the US dollar at 1.79 per USD.
Why legacy codes stay in historical data
A rate for LTL on 30 December 2014 is real, correct data – it is what Lithuanian businesses used that day. Removing it would break every system that needs to:
- Reproduce old invoices and reports in their original currency.
- Audit past transactions and the rates applied at the time – see accounting and financial reporting.
- Build long time series that span a currency change, for example Croatian prices from 2010 to today.
- Migrate ERP data without rewriting history – see ERP integration.
That is why fxapi keeps 11 legacy codes for history – BYR, CUC, HRK, LTL, LVL, MRO, SLL, STD, VEF, ZMK and ZWL – next to their successors, with daily historical exchange rates back to 1999-01-01. New codes such as VES, MRU, STN, SLE, ZWG and XCG are available as both base_currency and target. The authoritative list of what fxapi supports is /v1/currencies.
How to handle currency code changes in code
1. Never hard-code the currency list
Load supported codes from /v1/currencies (or the SIX list) at startup and cache them for a day. Reject unknown codes with a clear error instead of silently converting at 0 or 1.
2. Keep the original currency on every record
Store the amount and the currency code exactly as transacted (1500.00 HRK), plus the date. Convert for reporting in a separate column. Never overwrite the original.
3. Use the official ratio, not a market rate
To express a pre-2023 kuna amount in euros, divide by 7.53450. Don’t look up an “HRK→EUR exchange rate” for a date after the changeover – the official ratio is exact and legally defined.
4. Choose the code by date
For a transaction date, pick the code that was valid then: HRK before 1 January 2023, EUR from that date. Data entry screens and imports should validate the pair (code, date).
5. Round with the successor’s minor unit
After conversion, round to the new currency’s decimals. The currency rounding and precision guide covers the details.
Example: normalize legacy amounts in Python
A small mapping with exact Decimal ratios converts legacy amounts to their successor currency. Look up exchange rates with fxapi only after normalizing:
from decimal import Decimal, ROUND_HALF_UP
# code: (successor, old units, new units) → new = amount * new_units / old_units
LEGACY = {
"HRK": ("EUR", Decimal("7.53450"), Decimal("1")),
"LTL": ("EUR", Decimal("3.45280"), Decimal("1")),
"LVL": ("EUR", Decimal("0.702804"), Decimal("1")),
"BYR": ("BYN", Decimal("10000"), Decimal("1")),
"MRO": ("MRU", Decimal("10"), Decimal("1")),
"STD": ("STN", Decimal("1000"), Decimal("1")),
"VEF": ("VES", Decimal("100000"), Decimal("1")),
"SLL": ("SLE", Decimal("1000"), Decimal("1")),
"ZMK": ("ZMW", Decimal("1000"), Decimal("1")),
"CUC": ("CUP", Decimal("1"), Decimal("24")),
}
def normalize(amount: Decimal, code: str, places: int = 2) -> tuple[Decimal, str]:
if code not in LEGACY:
return amount, code
successor, old_units, new_units = LEGACY[code]
converted = amount * new_units / old_units
return converted.quantize(Decimal(1).scaleb(-places), rounding=ROUND_HALF_UP), successor
print(normalize(Decimal("1500.00"), "HRK")) # (Decimal('199.08'), 'EUR')
print(normalize(Decimal("250000"), "SLL")) # (Decimal('250.00'), 'SLE')
To value a legacy amount in another currency on its original date, keep the legacy code and call /v1/historical:
curl -G "https://api.fxapi.com/v1/historical" \
-d date=2014-12-30 \
-d base_currency=LTL \
-d currencies=USD,EUR \
-H "apikey: $FXAPI_KEY"
Key takeaways
- Currencies are redenominated, replaced and withdrawn regularly; ISO 4217 assigns new codes each time.
- Keep legacy codes and their history – they are needed for audits, reports and long time series.
- Convert old amounts with the official fixed ratio, choose codes by transaction date, and never hard-code the currency list.
- Use historical exchange rates for the old code on old dates. For the basics of rate data, read what is an exchange rate API.
Want to try it? fxapi is a FX rates API that returns live and historical rates for 190+ currencies as JSON – free for up to 300 requests a month.