Emerging markets are covered unevenly, so a comparison needs a coverage test. Narwhal returns monthly inflation, the policy rate and GDP growth for Indonesia and Brazil, and annual World Bank series for countries whose monthly routes have no data.
Request inflation for one emerging market
curl -s "https://api.narwhalapi.com/v1/economics/IDN/inflation" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"country": "IDN",
"period": "2026-09",
"year_over_year": "3.28",
"month_over_month": "0.3",
"released_on": "2026-10-29",
"source": {
"publisher": "Statistics Indonesia (BPS)",
"distributor": "OECD"
}
}year_over_year and month_over_month are percent, period is the month covered and released_on is the day it came out. Where the statistics office is known, source names the publisher and the distributor. The policy rate route has the same shape for every country: GET /v1/economics/{country}/central-bank/policy-rate returned rate 5.75 for Indonesia with instrument bi_rate and 13.75 for Brazil with instrument selic_target. Growth comes from GET /v1/economics/{country}/gdp-growth.
Test which countries answer
Coverage differs by country and by series, so test each pair instead of assuming a full set. These are the HTTP results for six large emerging markets.
| Country | Inflation | Policy rate | GDP growth | Unemployment |
|---|---|---|---|---|
| Indonesia (IDN) | 200 | 200 | 200 | 404 |
| Brazil (BRA) | 200 | 200 | 200 | 404 |
| Mexico (MEX) | 200 | 404 | 200 | 200 |
| India (IND) | 404 | 404 | 200 | 200 |
| South Africa (ZAF) | 404 | 404 | 200 | 200 |
| Turkey (TUR) | 404 | 404 | 404 | 404 |
A 404 carries the problem code series_not_found. It means that route has no published series for that country, so treat it as a gap and keep going. Run the same loop over any other country codes you need before you design the layout, because one run shows which cells of the grid can be filled from monthly routes and which need the annual fallback.
Read growth for the same countries
GET /v1/economics/{country}/gdp-growth returns year_over_year, quarter_over_quarter, period and released_on. The release dates differ a lot between countries, so print released_on beside the figure.
| Country | Period | Year over year | Quarter over quarter | Released on |
|---|---|---|---|---|
| Indonesia | 2026-Q2 | 5.3 | 1.3 | 2026-10-30 |
| Brazil | 2026-Q2 | 1.9 | 0.5 | 2026-10-30 |
| Mexico | 2026-Q2 | 1.9 | 1.4 | 2026-08-24 |
| South Africa | 2026-Q2 | 0.9 | -0.2 | 2026-09-08 |
The South Africa response carries year_over_year_not_seasonally_adjusted and India's carries not_seasonally_adjusted. Read those flags before you put two countries on one chart.
Fill gaps with annual World Bank data
Where the monthly route has no series, the catalogue can still hold an annual one. GET /v1/economics/catalogue searches by q and source. A search for inflation in the wdi source returns an id_template with a {country} slot. Replace the slot with the lower case three letter code, such as wdi:fp.cpi.totl.zg/ind for India.
curl -s "https://api.narwhalapi.com/v1/economics/catalogue?source=wdi&q=inflation&limit=1" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"results": [
{
"id_template": "wdi:fp.cpi.totl.zg/{country}",
"source": "wdi",
"title": "Inflation, consumer prices (annual %)",
"frequency": "annual",
"unit_label": "Inflation, consumer prices (annual %)"
}
]
}Read the observations with GET /v1/economics/catalogue/series/observations?id=..., using start and end as years for an annual series. Each response repeats the attribution and licence_url, so keep them next to any chart. Turkey is a good test, since the monthly routes have nothing for it.
curl -s "https://api.narwhalapi.com/v1/economics/catalogue/series/observations?id=wdi:fp.cpi.totl.zg/tur&start=2024&end=2025" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"id": "wdi:fp.cpi.totl.zg/tur",
"title": "Inflation, consumer prices (annual %), Turkiye",
"country": "TUR",
"frequency": "annual",
"unit_label": "Inflation, consumer prices (annual %)",
"attribution": "World Bank, World Development Indicators, CC BY 4.0. Values normalised by Narwhal.",
"observations": [
{
"period": "2024",
"value": "58.5064492168435"
},
{
"period": "2025",
"value": "34.8811700293777"
}
]
}Put the countries side by side
- Request monthly data first For each country the script asks for inflation and the policy rate. A 404 returns
None. - Fall back to the annual series If monthly inflation is missing, it reads the World Bank annual series for 2025 and labels the line as annual. It retries once on a 503.
- Compute the gap Where both inflation and a policy rate exist, it prints the policy rate minus inflation in percentage points.
import os import time import requests BASE = "https://api.narwhalapi.com" HEAD = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"} def get(path, **params): for _ in range(2): r = requests.get(BASE + path, params=params, headers=HEAD, timeout=15) if r.status_code != 503: break time.sleep(3) if r.status_code == 404: return None r.raise_for_status() return r.json() for c in ("IDN", "BRA", "MEX", "IND", "ZAF", "TUR"): infl = get(f"/v1/economics/{c}/inflation") rate = get(f"/v1/economics/{c}/central-bank/policy-rate") if infl: line = f"{c} inflation {infl['year_over_year']}% ({infl['period']})" else: wb = get("/v1/economics/catalogue/series/observations", id=f"wdi:fp.cpi.totl.zg/{c.lower()}", start="2025", end="2025") v = wb["observations"][0] line = f"{c} inflation {float(v['value']):.2f}% (annual {v['period']}, World Bank)" if rate: line += f" | policy rate {rate['rate']}%" if infl: line += f" | gap {float(rate['rate']) - float(infl['year_over_year']):.2f}" else: line += " | no policy rate" print(line)
The run printed the following.
| Country | Inflation | Basis | Policy rate | Policy rate minus inflation |
|---|---|---|---|---|
| IDN | 3.28% | Monthly, 2026-09 | 5.75% | 2.47 |
| BRA | 4.58% | Monthly, 2026-09 | 13.75% | 9.17 |
| MEX | 3.45% | Monthly, 2026-09 | none | none |
| IND | 2.40% | Annual, 2025 | none | none |
| ZAF | 3.21% | Annual, 2025 | none | none |
| TUR | 34.88% | Annual, 2025 | none | none |
Do not rank the annual rows against the monthly ones. A year-on-year rate for one month and a full-year rate cover different spans, so the Basis column goes next to every figure.
Why is Brazil's rate gap so much larger than Indonesia's?
The gap is the policy rate minus year-on-year inflation, 13.75 less 4.58 for Brazil and 5.75 less 3.28 for Indonesia. It is a simple difference of two published numbers. For the exact form that divides one plus the rate by one plus inflation, see calculate the real interest rate.
Can I get a country that has no series by changing the route?
Not every country is covered by the monthly routes. Search the catalogue for a series with the same meaning, as the Turkey example does, and read its frequency before you compare it with a monthly figure.
Why did a catalogue call return 503?
A World Bank series that has not been read before can come back with 503 and the code upstream_busy. A second call a few seconds later succeeded for the series tested, so the script waits and retries once. The catalogue search itself answered 200 each time, and the 503 appeared on the series read.
Published .