Guide 12 · updated 2026-10-16

ECOS exchange rate API: prevent selecting a non-USD currency

Valid ECOS JSON can still be interpreted as the wrong currency. Select and validate the USD item explicitly; never turn the first row into a compatibility fallback when the expected currency is absent.

By API Atlas · Reviewed:

Symptoms

A response is valid JSON and DATA_VALUE is numeric, yet the stored rate belongs to another currency. The reviewed legacy ECOS parser searches ITEM_NAME1 or ITEM_NAME2 for a USD identity, but still contains a first-row compatibility fallback when no match is found. That remaining fallback matters: the evidence does not justify saying every application path is fixed. The pinned application lock contains httpx==0.28.1; the example below uses only Python’s decimal module.

Cause

The 731Y001 statistics table is not itself proof that every returned row is USD/KRW. A separate reviewed collection path requests 731Y001/D/.../0000001, while a generic parser must still establish what it received. A row’s position and a plausible value are not currency identity. The official ECOS service remains the authority for current table and item definitions.

Safe resolution

The reduced parser requires the expected item code and a consistent USD name, rejects ambiguous or missing matches, and parses the original value as Decimal. Its ITEM_CODE1 requirement is an explicit stricter application contract; adapt it only after checking the response schema of the endpoint you actually request.

from decimal import Decimal, InvalidOperation

def select_usd_krw(payload):
    rows = payload["StatisticSearch"]["row"]
    if isinstance(rows, dict):
        rows = [rows]
    if not isinstance(rows, list):
        raise ValueError("Expected ECOS rows")
    matches = [
        row for row in rows
        if isinstance(row, dict)
        and row.get("ITEM_CODE1") == "0000001"
        and ("미국달러" in str(row.get("ITEM_NAME1", ""))
             or "usd" in str(row.get("ITEM_NAME1", "")).lower())
    ]
    if len(matches) != 1:
        raise ValueError("USD/KRW row missing or ambiguous")
    raw = matches[0].get("DATA_VALUE")
    if not isinstance(raw, str):
        raise ValueError("Expected original ECOS value text")
    try:
        rate = Decimal(raw.replace(",", ""))
    except InvalidOperation as exc:
        raise ValueError("Invalid ECOS rate") from exc
    if not rate.is_finite() or rate <= 0:
        raise ValueError("Invalid ECOS rate")
    return rate

Verification

Synthetic Python examples were checked on 2026-10-16; the original application tests and live provider APIs were not run.

Put a non-USD row before the USD row and assert the selected value does not depend on row order. Test a response with only EUR, two USD matches, an Australian-dollar item, non-finite/zero/malformed values, and a prematurely parsed float. Each invalid fixture must fail rather than return the first numeric value. All fixture amounts are synthetic; they are not market observations.

The checked-in tests extract this published Python block and exercise the same synthetic boundary cases. Re-run with npm test.

Limitations

This snippet is a proposed strict boundary, not a statement that the legacy first-row fallback was removed from every deployed application path. Validate observation dates, requested windows, units and persistence provenance separately. Different ECOS tables may use different item fields; do not copy 0000001 into an unrelated table. Repository source links may require access, and no authenticated ECOS request or original application test was run. See the BOK ECOS profile.

Implementation evidence was reviewed at pinned GetBeta revision 890c2531b76c. Source-repository links may require access; the public code above is a reduced adaptation without credentials or customer data. Search expressions are candidates, with no search-volume, indexing or ranking claim.

Sources and verification scope

Synthetic Python examples were checked on 2026-10-16; the original application tests and live provider APIs were not run.

Related providers