Financial Literature

Bank Negara Malaysia

BNM OpenAPI — Malaysia's OPR, ringgit rates, KLIBOR and reserves — a documented JSON API with no key

For Malaysian monetary data from the source — the Overnight Policy Rate, exchange rates, KLIBOR, interest rates, international reserves — with a clean, documented API.

ratesfxmoneyMalaysia
Asset classesrates · fx · money
Frequencydaily → monthly
History2004 → today
Limit · costNo key · versioned Accept header required
KeyNo key — No key, but send Accept: application/vnd.BNM.API.v1+json or the API returns an error.
Formats · pull withjson — python, excel
LicenceFree to use with attribution to Bank Negara Malaysia.
RedistributeWith attribution; check series notes
Best for“Malaysia's policy rate and its history” · “Ringgit per dollar, daily, from the central bank”
When to use it

Reach for it when…

For Malaysian monetary data from the source — the Overnight Policy Rate, exchange rates, KLIBOR, interest rates, international reserves — with a clean, documented API.

Not for: Malaysian CPI and GDP (the Department of Statistics Malaysia, OpenDOSM), Bursa Malaysia prices, regional comparisons (World Bank, BIS).

How to read it

Units, revisions, traps

Units. Rates in percent; exchange rates in ringgit per unit of foreign currency (buying and selling, at 09:00, 12:00 and 17:00 sessions); reserves in US$ billions.

Revisions. Not revised.

  • Three daily sessions for exchange rates — pick one (1700 is the closing session).
  • The OPR endpoint returns only changes; a year with no decision returns an empty list.
  • The versioned Accept header is mandatory.

Classic mistake: Averaging the buying and selling rates and calling it the mid-market rate for a specific time.

How to use it in your own work

Three recipes

Each recipe: Python · Excel · Sheets, with how to read the result. Python recipes run under pandas; recipe 1 is re-run by the weekly check where the source allows it.

How to use it in your own work

Copy the snippet, change the series id, read the result the way the footer says. Replace YOUR_…_KEY with your own key where one is needed.

Recipe 1OPR decisions by year

import requests, pandas as pd
H = {"Accept": "application/vnd.BNM.API.v1+json"}
rows = []
for y in range(2020, 2027):
    rows += requests.get(f"https://api.bnm.gov.my/public/opr/year/{y}", headers=H, timeout=30).json().get("data", [])
df = pd.DataFrame(rows)
print(df[["date", "change_in_opr", "new_opr_level"]])
How to read the resultMalaysia moves in 25-basis-point steps and rarely; the level against CPI (from DOSM) is the real-rate story.

Recipe 2Ringgit per dollar, closing session

import requests, pandas as pd
H = {"Accept": "application/vnd.BNM.API.v1+json"}
u = "https://api.bnm.gov.my/public/exchange-rate/USD/year/2026?session=1700&quote=rm"
df = pd.DataFrame(requests.get(u, headers=H, timeout=30).json()["data"])
df = pd.json_normalize(df.to_dict("records"))
print(df[["date", "rate.buying_rate", "rate.selling_rate"]].tail())
How to read the resultQuote=rm gives ringgit per dollar: a rising number is a weaker ringgit.

Recipe 3International reserves

import requests, pandas as pd
H = {"Accept": "application/vnd.BNM.API.v1+json"}
u = "https://api.bnm.gov.my/public/msb/1.3?year=2026"   # Monthly Statistical Bulletin table 1.3
j = requests.get(u, headers=H, timeout=30).json()
print(pd.DataFrame(j["data"]).tail())
How to read the resultReserves in months of imports is the readable ratio; BNM publishes it in the same table.

Series → question map

The ids we use from BNM OpenAPI, each with the question it answers. The catalog's compare view reads the concept tags behind these rows.

SeriesAnswersRegionConcept
oprWhat is Malaysia's policy rate?Malaysiapolicy_rate
exchange-rate/USDRinggit per dollar, dailyMalaysiafx_usd
kliborWhat is KLIBOR?Malaysiainterbank
msb/1.3How large are Malaysia's reserves?Malaysiareserves

Compare with

Same question, different source: HKMA API, SingStat Table Builder API, BIS Data Portal. The compare view lines up coverage, frequency, history and access side by side and lists what the combination makes possible.

Open compare: BNM OpenAPI · HKMA API · SingStat Table Builder API →

Questions readers ask

Why does BNM return 'not acceptable'?

The Accept header is missing or unversioned. Send Accept: application/vnd.BNM.API.v1+json.

Where is Malaysian CPI?

OpenDOSM (open.dosm.gov.my) has a free API for CPI, GDP and labour data.

Is there history before 2004?

Not through the API; the Monthly Statistical Bulletin PDFs go further back.

From the paper

Educational only — we explain, we never advise · snippet licence: public domain · corrections to [email protected], fixed within a day and logged in the changelog.