SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
38.4 KB

# CountryAtlas — Public data sources, verified 2026-09-11

Every URL below was called with curl on 2026-09-11 from Québec (all times UTC). "VERIFIED" = HTTP 200 with data shown. "UNVERIFIED" = could not confirm; what was tried is stated. Samples are trimmed.

Summary table

Source Base URL Auth Rate limit (observed / documented) Country code Time format Licence
World Bank WDI v2 https://api.worldbank.org/v2/ none none published; Cloudflare-cached (cache-control: max-age≈30000) ISO3 in countryiso3code, WB 2-letter in country.id "2025" (year string) CC BY 4.0 (attribute "World Bank, World Development Indicators")
IMF WEO (SDMX) https://api.imf.org/external/sdmx/{2.1,3.0}/ none none observed; 3.6 MB CSV for all countries in <10 s ISO3 (CAN) + IMF group codes (G001…) year 2024 © IMF, free reuse with citation (see LICENSE field)
OECD SDMX https://sdmx.oecd.org/public/rest/ none doc: 60 req/h per IP for anonymous… see §3 (not enforced on our tests) ISO3 (REF_AREA) 2024, 2026-06, 2026-Q1 CC BY 4.0
Eurostat JSON-stat https://ec.europa.eu/eurostat/api/dissemination/statistics/1.0/data/ none doc: no hard limit; large queries may be refused Eurostat geo (EL, EU27_2020) 2025, 2025-M06, 2025-Q1 CC BY 4.0
WHO GHO OData https://ghoapi.azureedge.net/api/ none none published; CDN max-age=3600 ISO3 (SpatialDim) TimeDim int year CC BY-NC-SA 3.0 IGO
FRED https://api.stlouisfed.org/fred/ api_key 120 req/min; bursts trigger 429 then Akamai 403 for several minutes US mostly; ISO2 embedded in ids (QCAR628BIS) 2026-08-01 (ISO date) FRED ToU; third-party series keep their own terms
OWID raw.githubusercontent.com/owid/..., ourworldindata.org/grapher/ none GitHub raw: reasonable; grapher CSV: none published ISO3 in iso_code/code; OWID_* for aggregates year int CC BY 4.0
UN WPP portal API https://population.un.org/dataportalapi/api/v1/ Bearer token for /data/* n/a UN M49 numeric location ids year CC BY 3.0 IGO
UN Comtrade https://comtradeapi.un.org/ subscription key (free /public/v1/preview limited) preview: 500 records/call M49 numeric (124) period=2023 UN ToU
BIS SDMX v2 https://stats.bis.org/api/v2/ none none observed ISO2 (CA, US, XM=euro area) 2026-08, 2026-Q1 BIS terms (free with attribution)
ILOSTAT SDMX https://sdmx.ilo.org/rest/ none cache-control: no-store; none published ISO3 year CC BY 4.0

# 1. World Bank Indicators API v2 — VERIFIED

Base https://api.worldbank.org/v2/, no auth, format=json. Response is a 2-element array: [meta, rows]. Meta: {"page":1,"pages":1,"per_page":20000,"total":17490,"sourceid":"2","lastupdated":"2026-07-13"} — lastupdated is the WDI vintage (2026-07-13 on all WDI queries).

# Country list (regions, income groups, aggregates)

GET /country?format=json&per_page=400 → total: 295 (217 economies + 78 aggregates). Aggregates have region.id == "NA" (and incomeLevel.id == "NA").

json
{"id":"CAN","iso2Code":"CA","name":"Canada","region":{"id":"NAC","iso2code":"XU","value":"North America"},
 "adminregion":{"id":"","iso2code":"","value":""},"incomeLevel":{"id":"HIC","iso2code":"XD","value":"High income"},
 "lendingType":{"id":"LNX","iso2code":"XX","value":"Not classified"},"capitalCity":"Ottawa","longitude":"-75.6919","latitude":"45.4215"}
{"id":"WLD","iso2Code":"1W","name":"World","region":{"id":"NA","iso2code":"NA","value":"Aggregates"}, ...}

Filter aggregates with region.id == "NA" → 78 (WLD, EUU, HIC, OED, LIC, LMC, UMC, AFE, …). Real economies: 217.

# Indicator data, all countries

GET /country/all/indicator/NY.GDP.PCAP.CD?format=json&per_page=20000&date=1960:2026 → 17 490 rows, 1 page.

json
{"indicator":{"id":"NY.GDP.PCAP.CD","value":"GDP per capita (current US$)"},"country":{"id":"1W","value":"World"},
 "countryiso3code":"WLD","date":"2025","value":14405.8484595528,"unit":"","obs_status":"","decimal":1}
  • Rows are sorted country → year descending. Missing values: "value": null (2 745 of 17 490 here). obs_status is essentially always "".
  • Data rows include aggregates (WLD, EUU, HIC…). Join on countryiso3code with the country list to drop them.
  • Quirk: 5 income-group aggregates (XD High income, XM Low, XN Lower-middle, XT Upper-middle, XY Not classified) come back with countryiso3code: "" — use country.id (2-letter) as a fallback key.
  • per_page: default 50 (→ pages: 350). Tested 20 000, 25 000 and 32 000 → OK. 50 000 → HTTP "Request Error" XML page. Use ≤ 32 000; one indicator for all countries/years fits in one page (~17.5k rows).
  • date=1960:2026 (range) or date=2024; mrv=N = N most-recent values per country; mrnev=1 = most recent non-empty value (returns fewer rows, e.g. Gini CAN → 2022); gapfill=Y with mrv forward-fills (Gini CAN 2023–2025 all 31.5 — beware).
  • Several countries: /country/CAN;USA/indicator/.... Several indicators: /country/CAN/indicator/SP.POP.TOTL;NY.GDP.MKTP.CD?source=2 (needs source=).
  • Retired code → HTTP 200 with [{"message":[{"id":"175","key":"Invalid format","value":"The indicator was not found. It may have been deleted or archived."}]}] — check for .[0].message, not the status code.

# Indicator metadata

GET /indicator/NY.GDP.PCAP.CD?format=json →

json
{"id":"NY.GDP.PCAP.CD","name":"GDP per capita (current US$)","unit":"","source":{"id":"2","value":"World Development Indicators"},
 "sourceNote":"Gross domestic product is the total income earned ...","sourceOrganization":"Country official statistics, ...; OECD; Staff estimates, World Bank (WB)",
 "topics":[{"id":"3","value":"Economy & Growth"}]}

Full catalogue: /indicator?format=json&per_page=30000 (29 544 indicators, 6 MB) — filter locally (source.id=="2" → 1 498 WDI indicators). The q= search parameter is ignored (returns the full list). /source?format=json&per_page=100 → 71 sources; /source/2?format=json → {"id":"2","lastupdated":"2026-07-13","name":"World Development Indicators","code":"WDI"}.

# Indicator code audit (mrnev=1&per_page=400 on /country/all/...)

Exist and return data (94/96) — latest year with data (CAN value in brackets):

Code Latest Code Latest Code Latest
NY.GDP.MKTP.CD 2025 NY.GDP.PCAP.CD 2025 (55 698) NY.GDP.PCAP.PP.CD 2025
NY.GDP.MKTP.KD.ZG 2025 FP.CPI.TOTL.ZG 2025 SL.UEM.TOTL.ZS 2025
SP.POP.TOTL 2025 SP.POP.GROW 2025 SP.DYN.LE00.IN 2024
SP.DYN.TFRT.IN 2024 SP.URB.TOTL.IN.ZS 2025 GC.DOD.TOTL.GD.ZS 2024 (120 countries only)
EN.GHG.CO2.PC.CE.AR5 2024 (14.0 t) EG.ELC.RNEW.ZS 2021 IT.NET.USER.ZS 2025
GB.XPD.RSDV.GD.ZS 2024 NE.EXP.GNFS.ZS 2025 NE.TRD.GNFS.ZS 2025
SH.XPD.CHEX.GD.ZS 2024 SE.XPD.TOTL.GD.ZS 2025 SP.DYN.IMRT.IN 2024
SI.POV.GINI 2025 (CAN 2022) SL.TLF.CACT.ZS 2025 MS.MIL.XPND.GD.ZS 2024
EG.USE.PCAP.KG.OE 2024 EG.FEC.RNEW.ZS 2022 AG.LND.FRST.ZS 2023
EN.ATM.PM25.MC.M3 2023 IT.CEL.SETS.P2 2025 IT.NET.BBND.P2 2025
ST.INT.ARVL 2020 BN.CAB.XOKA.GD.ZS 2025 GC.REV.XGRT.GD.ZS 2024
GC.XPN.TOTL.GD.ZS 2024 SH.MED.PHYS.ZS 2023 SH.MED.BEDS.ZS 2023
SM.POP.NETM 2025 SP.POP.65UP.TO.ZS 2025 SP.POP.0014.TO.ZS 2025
NV.AGR.TOTL.ZS 2025 NV.IND.TOTL.ZS 2025 NV.SRV.TOTL.ZS 2025
FR.INR.LEND 2025 (CAN stops 2017) PA.NUS.FCRF 2025 EG.ELC.ACCS.ZS 2024
SH.STA.SUIC.P5 2021 SH.PRV.SMOK 2024 SE.ADT.LITR.ZS 2024 (no CAN)
SE.TER.ENRR 2025 SE.SEC.ENRR 2025 SE.PRM.ENRR 2025
SL.UEM.1524.ZS 2025 AG.PRD.FOOD.XD 2022 AG.LND.AGRI.ZS 2023
NY.GDP.TOTL.RT.ZS 2021 ER.LND.PTLD.ZS 2025 EN.POP.DNST 2023
SP.POP.DPND 2025 VC.IHR.PSRC.P5 2023 SH.XPD.CHEX.PC.CD 2024
NY.GDP.PCAP.KD.ZG 2025 NE.GDI.TOTL.ZS 2025 NE.CON.PRVT.ZS 2025
FM.LBL.BMNY.GD.ZS 2025 (CAN stops 2008) BX.KLT.DINV.WD.GD.ZS 2025 DT.DOD.DECT.GN.ZS 2024 (133 low/middle income only)
SL.GDP.PCAP.EM.KD 2025 EG.IMP.CONS.ZS 2023 EG.EGY.PRIM.PP.KD 2022
SH.DYN.MORT 2024 SH.DYN.NCOM.ZS 2021 SP.ADO.TFRT 2024
SH.STA.OWAD.ZS 2022 (overweight, not obesity; source 16 HNP) SP.DYN.CBRT.IN 2024 SP.DYN.CDRT.IN 2024
SM.POP.TOTL.ZS 2024 IP.PAT.RESD 2021 IP.JRN.ARTC.SC 2023
TX.VAL.TECH.MF.ZS 2024 LP.LPI.OVRL.XQ 2022 IS.AIR.PSGR 2023
IS.RRS.TOTL.KM 2021 EG.ELC.FOSL.ZS 2023 EG.ELC.HYRO.ZS 2024
EG.ELC.NUCL.ZS 2024 EG.ELC.RNWX.ZS 2021 EN.GHG.CO2.MT.CE.AR5 2024
EN.GHG.CH4.MT.CE.AR5 2024 GC.TAX.TOTL.GD.ZS 2024 SH.H2O.BASW.ZS 2024
SE.PRM.CMPT.ZS 2025

Missing (2/96):

  • EN.ATM.CO2E.PC — retired. Replacement EN.GHG.CO2.PC.CE.AR5 (t CO2e/capita, excl. LULUCF, source EDGAR). Sibling codes verified: EN.GHG.CO2.MT.CE.AR5, EN.GHG.CH4.MT.CE.AR5, EN.GHG.N2O.MT.CE.AR5, EN.GHG.ALL.MT.CE.AR5 (total GHG Mt), EN.GHG.ALL.PC.CE.AR5 (total GHG per capita, CAN 2024 = 18.6).
  • SM.POP.REFG — listed in the catalogue under source 57 "WDI Database Archives" but returns "not found" both with and without source=57. Replacement: UNHCR Refugee Data Finder API (https://api.unhcr.org/population/v1/population/?year=2024&coa=CAN, no key) or OWID grapher refugee-population-by-country-or-territory-of-asylum. Not tested here.
  • Obesity: WB has no adult obesity (BMI≥30) indicator (catalogue search found only overweight SH.STA.OWAD.ZS and HEFPI mean-BMI). Use WHO NCD_BMI_30A (§5).

# 2. IMF World Economic Outlook — VERIFIED (no key needed)

  • Legacy dataservices.imf.org/REST/SDMX_JSON.svc → connection fails (retired).
  • New portal https://data.imf.org exposes SDMX 2.1 and 3.0 REST at https://api.imf.org/external/sdmx/, no API key, no subscription. (An IMF "Data Portal Subscription" only raises quotas; anonymous works.)
  • Dataflow IMF.RES,WEO (agency IMF.RES, id WEO, version 9.0.0), DSD DSD_WEO.
  • Dimension order: COUNTRY.INDICATOR.FREQUENCY (+ TIME_PERIOD); FREQUENCY is always A.
  • Current vintage: PUBLICATION_DATE 2026-04-14 = April 2026 WEO (visible in CSV metadata). Years 1980–2031 (52 periods).
text
GET https://api.imf.org/external/sdmx/2.1/data/IMF.RES,WEO/CAN+USA.NGDP_RPCH+PCPIPCH+LUR+GGXWDG_NGDP+GGXCNL_NGDP+BCA_NGDPD+PPPPC.A?startPeriod=2024&endPeriod=2031
Accept: text/csv
text
DATAFLOW,COUNTRY,INDICATOR,FREQUENCY,TIME_PERIOD,OBS_VALUE,SCALE,...,LATEST_ACTUAL_ANNUAL_DATA,...
IMF.RES:WEO(9.0.0),CAN,LUR,A,2024,6.366667,0,...,2025,...
IMF.RES:WEO(9.0.0),CAN,LUR,A,2025,6.858333,0,...,2025,...
IMF.RES:WEO(9.0.0),CAN,LUR,A,2026,6.521412,0,...,2025,...
  • Projection flag: column LATEST_ACTUAL_ANNUAL_DATA (per country×indicator; here 2025) = "estimates start after". Any TIME_PERIOD > LATEST_ACTUAL_ANNUAL_DATA is a forecast. Present in CSV output only (2.1 XML has it as series attribute too; SDMX-JSON 3.0 exposes it in attributes if requested with attributes=all, not confirmed).
  • CSV also carries LICENSE ("© International Monetary Fund Copyright. All Rights Reserved. https://www.imf.org/external/terms.htm") and SUGGESTED_CITATION: "International Monetary Fund. World Economic Outlook (WEO), https://data.imf.org/en/datasets/IMF.RES:WEO. Accessed on [date]."
  • All countries: leave the COUNTRY segment empty: /data/IMF.RES,WEO/.NGDP_RPCH.A?startPeriod=2024 → 1 640 rows, 213 areas (incl. aggregates G001 World etc.), 3.6 MB CSV (the CSV repeats ~40 metadata columns per row — parse COUNTRY,INDICATOR,TIME_PERIOD,OBS_VALUE,LATEST_ACTUAL_ANNUAL_DATA).
  • Default 2.1 output (no Accept) is SDMX-ML StructureSpecific XML: <Series COUNTRY="CAN" INDICATOR="NGDP_RPCH" FREQUENCY="A" ...><Obs TIME_PERIOD="2026" OBS_VALUE="1.499992"/>. Asking Accept: application/vnd.sdmx.data+json on 2.1 still returns XML (JSON not served on 2.1).
  • Quirk: the + separator in the 2.1 key with the JSON Accept header once returned HTTP 500; CSV/XML fine. dataflow/IMF.RES/WEO/+ on 2.1 → 204 (use 3.0 for structures).

# SDMX 3.0 (JSON)

text
GET https://api.imf.org/external/sdmx/3.0/data/dataflow/IMF.RES/WEO/+/CAN.NGDP_RPCH.A
Accept: application/vnd.sdmx.data+json;version=2.0.0
json
{"data":{"dataSets":[{"series":{"0:0:0":{"attributes":[0,0,0,"9/25/2025"],"observations":{"0":["2.162741"],"1":["3.503078"],...}}}}],
 "structures":[{"dimensions":{"series":[{"id":"COUNTRY","keyPosition":0},{"id":"INDICATOR","keyPosition":1},{"id":"FREQUENCY","keyPosition":2}],
 "observation":[{"id":"TIME_PERIOD","values":[{"value":"1980"},...]}]}}]}}
  • Wildcard all countries: .../WEO/+/*.NGDP_RPCH.A → 210 areas, 194 KB.
  • Time filter must be URL-encoded: ?c%5BTIME_PERIOD%5D=ge:2024 (raw c[TIME_PERIOD]= → HTTP 400 Tomcat page). Observation values are strings ("2.162741").
  • Structures: /3.0/structure/dataflow/IMF.RES/WEO/+, /3.0/structure/datastructure/IMF.RES/DSD_WEO/+, codelists IMF.RES/CL_WEO_INDICATOR (145 codes), IMF.RES/CL_WEO_COUNTRY (344 codes) with Accept: application/vnd.sdmx.structure+json;version=2.0.0.
  • Verified indicator codes: NGDP_RPCH (real GDP growth %), PCPIPCH (CPI inflation avg %), LUR (unemployment rate), GGXWDG_NGDP (gross debt % GDP), GGXCNL_NGDP (net lending % GDP), BCA_NGDPD (current account % GDP), PPPPC (GDP per capita PPP intl $), plus NGDPD, NGDPDPC, PPPGDP, LP (population), GGXWDN_NGDP (net debt).
  • Quirk: COUNTRY_UPDATE_DATE attribute reads 9/25/2025 even in the April 2026 vintage — do not use it as vintage; use PUBLICATION_DATE/UPDATE_DATE from CSV or the dataflow version.

# Bulk download fallback — UNVERIFIED

https://www.imf.org/-/media/Files/Publications/WEO/WEO-Database/2026/april/WEOApr2026all.ashx → 302 to Azure blob → BlobNotFound; .xls variants and the page imf.org/en/Publications/WEO/weo-database/2026/april/download-entire-database → 403 Akamai "Access Denied" for curl (browser UA too). The Oct-2025 and Apr-2025 .ashx URLs also 302→BlobNotFound. Conclusion: the tab-separated "WEO…all.xls" files are no longer served from that path; use the SDMX API above (or data.imf.org bulk "Download entire dataset" button, browser only).


# 3. OECD SDMX API — VERIFIED (5+ dataflows end-to-end)

Base https://sdmx.oecd.org/public/rest/. No key. Licence CC BY 4.0 (cite "OECD (2026), , https://data-explorer.oecd.org"). Documented limits (OECD API docs): 60 data requests/hour/IP anonymous, 1 000 000 obs/query; not hit during ~40 requests here. cache-control: public, max-age=7200 on data.

URL pattern: /data/{AGENCY},{DSD@DF},{version|blank}/{key}?startPeriod=…&format=csvfilewithlabels (CSV code+label columns) or format=csvfile or format=jsondata (SDMX-JSON 1.0). Key must contain every dimension (dots), empty = wildcard; missing dims → HTTP 403 Not enough key values in query, expecting N got M. Nothing found → HTTP 404 NoRecordsFound. Country dim REF_AREA = ISO3. Time: 2024, 2026-06, 2026-Q1. Current dataflow ids: GET /dataflow/all (XML, 8.9 MB, 1 546 flows; JSON Accept → 406). Structure: /dataflow/{AGENCY}/{DSD@DF}/latest?references=all or /datastructure/{AGENCY}/{DSD}/latest with Accept: application/vnd.sdmx.structure+json (dimension list under dataStructureComponents.dimensionList.dimensions).

Topic Dataflow (verified id) Dims (order) Working query (CAN+USA) Sample
House prices OECD.ECO.MPD,DSD_AN_HOUSE_PRICES@DF_HOUSE_PRICES REF_AREA.FREQ.MEASURE.UNIT_MEASURE /CAN+USA.A.RHP+HPI+RPI+HPI_RPI+HPI_YDH.?startPeriod=2021 CAN,A,RHP,IX,2021,144.49 (base 2015=100)
Short/long rates OECD.SDD.STES,DSD_STES@DF_FINMARK (4.0) REF_AREA.FREQ.MEASURE.UNIT_MEASURE.ACTIVITY.ADJUSTMENT.TRANSFORMATION.TIME_HORIZ.METHODOLOGY (9) /CAN+USA.M.IRSTCI+IR3TIB+IRLT.PA......?startPeriod=2026-06 CAN IRLT 2026-08 3.675
Rates (KEI) OECD.SDD.STES,DSD_KEI@DF_KEI (4.0) REF_AREA.FREQ.MEASURE.UNIT_MEASURE.ACTIVITY.ADJUSTMENT.TRANSFORMATION (7) /CAN+USA.M.IR3TIB+IRLT.....?startPeriod=2026-06 CAN IR3TIB 2026-08 2.28
Avg annual wages OECD.ELS.SAE,DSD_EARNINGS@AV_AN_WAGE REF_AREA.MEASURE.UNIT_MEASURE.PAY_PERIOD.PRICE_BASE.AGGREGATION_OPERATION.SEX (7) /CAN+USA.......?startPeriod=2021 CAN WG USD_PPP Q(constant) 2024 67767.6
Hours worked OECD.ELS.SAE,DSD_HW@DF_AVG_ANN_HRS_WKD 13 dims (REF_AREA.MEASURE.UNIT_MEASURE.SEX.AGE.LABOUR_FORCE_STATUS.WORK_PERIOD.HOURS_TYPE.WORKER_STATUS.WORK_TIME_ARNGMNT.AGGREGATION_OPERATION.HOUR_BANDS.JOB_COVERAGE) /CAN+USA............?startPeriod=2021 then filter WORKER_STATUS=_T CAN 2022 1693 h, USA 2023 1804.95
Tax revenue OECD.CTP.TPS,DSD_REV_COMP_OECD@DF_RSOECD (2.0) REF_AREA.MEASURE.SECTOR.STANDARD_REVENUE.CTRY_SPECIFIC_REVENUE.UNIT_MEASURE.FREQ (7) /CAN+USA.TAX_REV.S13._T._T.PT_B1GQ.A?startPeriod=2022 CAN _T 2023 34.79 % GDP (T_AA cash-basis is 0 for accrual reporters — use _T)
Social expenditure OECD.ELS.SPD,DSD_SOCX_AGG@DF_SOCX_AGG REF_AREA.FREQ.MEASURE.UNIT_MEASURE.EXPEND_SOURCE.SPENDING_TYPE.PROGRAMME_TYPE.PRICE_BASE (8) /CAN+USA.A.SOCX.PT_B1GQ.ES10._T._T.?startPeriod=2021 CAN ES10 (public) 2021 21.858 % GDP
Hospital beds OECD.ELS.HD,DSD_HEALTH_REAC_HOSP@DF_HOSP_REAC (1.1) REF_AREA.MEASURE.UNIT_MEASURE.STATISTICAL_OPERATION.OWNERSHIP_TYPE.HEALTH_FUNCTION.CARE_TYPE.MEDICAL_TECH.HEALTH_CARE_PROVIDER (9) /CAN+USA.HB.10P3HB.._T._T...?startPeriod=2022 CAN 2024 2.08 beds/1000 (HEALTH_FUNCTION=_T; HC0 rows are 0)
Physicians / nurses OECD.ELS.HD,DSD_HEALTH_EMP_REAC@DF_PHYS (also @DF_NURSE) — not DSD_HEALTH_REAC_EMP REF_AREA.MEASURE.UNIT_MEASURE.AGE.SEX.HEALTH_PROF.HEALTH_PROF_ACTIVITY_STATUS.… (9) /CAN+USA.........?startPeriod=2022 filter UNIT_MEASURE=10P3HB CAN HSE PHYS LP(practising) 2022 2.93/1000
R&D (MSTI) OECD.STI.STP,DSD_MSTI@DF_MSTI (1.3) REF_AREA.FREQ.MEASURE.UNIT_MEASURE.PRICE_BASE.TRANSFORMATION (6) /CAN.A.G.PT_B1GQ._Z._Z?startPeriod=2021 G PT_B1GQ 2023 1.935 (GERD % GDP); researchers T_RS FTE 2023 235170
Education attainment OECD.EDU.IMEP,DSD_EAG_LSO_EA@DF_LSO_NEAC_DISTR_EA (the DSD_EAG_UOE_NEAC@DF_EAG_NEAC id does not exist anymore) 17 dims; REF_AREA first /CAN+USA................?startPeriod=2023 filter AGE=Y25T64, SEX=_T, ATTAINMENT_LEV=ISCED11A_5T8, STATISTICAL_OPERATION=V structure verified; returned 3 945 rows; SE rows (std error) have empty OBS_VALUE — value rows use STATISTICAL_OPERATION=V (not individually displayed; partially verified)
Productivity OECD.SDD.TPS,DSD_PDB@DF_PDB_LV REF_AREA.FREQ.MEASURE.ACTIVITY.UNIT_MEASURE.PRICE_BASE.TRANSFORMATION.ASSET_CODE.CONVERSION_TYPE (9) /CAN+USA.A.......?startPeriod=2022 UNVERIFIED — HTTP 500 "Internal server error" on two attempts (structure endpoint OK). Retry later or use DSD_PDB@DF_PDB_GR.
CLI / confidence OECD.SDD.STES,DSD_STES@DF_CLI (4.1) as FINMARK not tested id present in flow list

CSV (csvfilewithlabels) columns: STRUCTURE,STRUCTURE_ID,STRUCTURE_NAME,ACTION,REF_AREA,Reference area,…,TIME_PERIOD,Time period,OBS_VALUE,Observation value,OBS_STATUS,… — every dimension is followed by its label column; parse with a CSV reader keyed by header (labels can contain commas). OBS_STATUS: A normal, E estimate, P provisional, B break. Empty OBS_VALUE = missing. format=jsondata sample (house prices): {"data":{"dataSets":[{"series":{"0:0:0:0":{"observations":{"0":[139.53,0],"1":[144.16,0],"2":[143.35,0]}}}}],"structure":{"dimensions":{"observation":[{"id":"TIME_PERIOD","values":[{"id":"2025"},{"id":"2024"},{"id":"2023"}]}]}}}} — time values come in descending order; map observation index → values[i].id, never assume ascending.

# Connector implementation notes (2026-09-11, registry/sources/oecd.yaml)

Full-dimension keys that returned data for ALL countries (REF_AREA empty) — the shorter keys in the table above 404 (NoRecordsFound) when used with an empty REF_AREA:

  • Wages DSD_EARNINGS@AV_AN_WAGE: .WG.USD_PPP.A.Q.MEAN._Z (PRICE_BASE Q = constant prices, base 2025; V = current).
  • Hours DSD_HW@DF_AVG_ANN_HRS_WKD: .HW.H_Y_PS._Z._Z.EMP.A.ACTUAL._T._Z.MEAN._Z._T (12 dims after REF_AREA).
  • Hospital beds DF_HOSP_REAC: .HB.10P3HB._Z._Z._T._T._Z._Z — the total is OWNERSHIP_TYPE=_Z, HEALTH_FUNCTION=_T, CARE_TYPE=_T; the .._T._T... form above no longer matches.
  • Physicians DF_PHYS: .HSE.10P3HB._Z._Z.PHYS._Z.LP._Z (practising; USA has LP too). DF_NURSE does not exist (404 "Could not find Dataflow").
  • Education DF_LSO_NEAC_DISTR_EA (17 dims): ._T.Y25T64.ISCED11A_5T8._T.POP._Z._T._Z.ED_NED.POP._Z.PT_POP_SEX_AGE.OBS._Z.NEAC.A — STATISTICAL_OPERATION is OBS/SE (not V); no ISCED 3–8 aggregate → "at least upper secondary" = 100 − ISCED11A_0T2. Includes OECD, G20, EU25 aggregates.
  • SOCX: last segment PRICE_BASE is _Z (.A.SOCX.PT_B1GQ.ES10._T._T._Z). KEI industrial production: .M.PRVM.IX.BTE.Y._Z (2015=100, monthly, back to 1919 for some countries).
  • DF_PDB_LV (GDP per hour worked) still HTTP 500 on 2026-09-11 (3 attempts) — not mapped.
  • Rate limit is real: 17 requests in ~40 s → one HTTP 429 (retried later). Keep ≤ 12/min.

# 4. Eurostat JSON-stat 2.0 — VERIFIED (13/13 — ilc_li02 works with statinfo=MED_EI, see note)

Base https://ec.europa.eu/eurostat/api/dissemination/statistics/1.0/data/{dataset}?format=JSON&lang=EN&{dim}={code}&…. No key. Filters: repeat geo=DE&geo=FR; time=2024 or sinceTimePeriod=2022 (untilTimePeriod, lastTimePeriod=N). Unknown dimension name → HTTP 400 {"error":[{"status":400,"id":150,"label":"INVALID_QUERY_DIMENSION: … Dimension \"INDIC_IL\" is not defined"}]}. Unknown code → 200 with size: [...,0,...] and empty value. Discover a dataset's dimensions/codes by requesting a single geo+time (.dimension.<dim>.category.index). Licence CC BY 4.0 ("Source: Eurostat").

Structure (HICP example) — value is a sparse object keyed by the flattened row-major index over size:

json
{"version":"2.0","class":"dataset","label":"HICP - annual data …","source":"ESTAT","updated":"2026-02-06T23:00:00+0100",
 "id":["freq","unit","coicop","geo","time"],"size":[1,1,1,4,4],
 "dimension":{"geo":{"category":{"index":{"EU27_2020":0,"DE":1,"EL":2,"FR":3},"label":{"EL":"Greece",…}}},
              "time":{"category":{"index":{"2022":0,"2023":1,"2024":2,"2025":3}}}},
 "value":{"0":9.2,"1":6.4,"2":2.6,"3":2.5,"4":8.7,"5":6.0,…},
 "status":{"8":"d","9":"d"}}

Index = geoIdx*size[time] + timeIdx (generally Σ idx_k·∏size_{k+1..}). Missing cells are simply absent from value. status flags: p provisional, e estimated, b break, d definition differs, u low reliability, : n/a. updated = dataset last update (freshness).

Dataset Verified query (after ?format=JSON&lang=EN&) updated Sample
prc_hicp_aind unit=RCH_A_AVG&coicop=CP00&geo=DE&geo=FR&geo=EL&geo=EU27_2020&sinceTimePeriod=2022 2026-02-06 EU27 2022 9.2 %
prc_hpi_a purchase=TOTAL&unit=RCH_A_AVG&geo=DE&geo=FR&sinceTimePeriod=2022 2026-07-02 DE 2022 6.0, 2023 -8.4
une_rt_a age=Y15-74&unit=PC_ACT&sex=T&geo=… 2026-09-10 DE 2022 3.1
gov_10dd_edpt1 na_item=GD&unit=PC_GDP&sector=S13&geo=DE&geo=FR&geo=IT 2026-04-22 DE 2022 64.4 %
lfsi_emp_a indic_em=EMP_LFS&unit=PC_POP&age=Y20-64&sex=T 2026-09-10 DE 2022 80.8
ilc_di03 statinfo=MED_EI&age=TOTAL&sex=T&unit=EUR (dimension is statinfo, not indic_il) 2026-06-08 DE 2022 24 925 €
ilc_li02 dims freq,statinfo,unit,rskpovth,sex,age,geo,time; rskpovth=A_60&unit=PC&sex=T&age=TOTAL 2026-06-10 UNVERIFIED values: every combination tested (DE/FR, 2019–2025, both statinfo, also SDMX-CSV endpoint) returns an empty value — dataset appears to be mid-revision. Use ilc_peps01n (AROPE rate; dims unit,age,sex; 204 values for DE 2024 — verified) or retry later.
rd_e_gerdtot sectperf=TOTAL&unit=PC_GDP 2026-03-18 DE 2022 3.07 (2024 p)
nrg_ind_ren nrg_bal=REN&unit=PC 2026-07-14 DE 2021 19.3
env_air_gge airpol=GHG&src_crf=TOTX4_MEMO&unit=MIO_T (not TOTX4_MEMONIA; units are MIO_T/THS_T, no T_HAB here) 2026-06-02 DE 2022 749.3, 2024 649.8 Mt CO2e
demo_mlexpec sex=T&age=Y_LT1 2026-06-04 DE 2022 80.7
edat_lfse_03 sex=T&age=Y25-64&isced11=ED5-8&unit=PC 2026-09-10 DE 2022 32.1
ilc_lvho07a rskpovth=TOTAL&age=TOTAL&sex=T&unit=PC (no incgrp dimension) 2026-06-08 DE 2022 11.9

Connector implementation notes (2026-09-11, registry/sources/eurostat.yaml) — ilc_li02 is NOT empty: the statinfo codes are MED_EI/MEAN_EI (there is no RT), so statinfo=MED_EI&rskpovth=B_60&unit=PC&sex=T&age=TOTAL returns the at-risk-of-poverty rate (DE 2024 15.5 %). Other verified filters: ilc_lvho02 (tenure) rskpovth=TOTAL&hhcomp=TOTAL&tenure=OWN&unit=PC (DE 2024 47.2 %); une_ltu_a indic_em=LTU&age=Y15-74&sex=T&unit=PC_UNE; lfsa_eppga sex=T&age=Y15-64&unit=PC; lfsi_emp_a has age=Y15-64; ilc_di03 unit=PPS (DE 2024 25 192); prc_hpi_a unit=I15_A_AVG for the 2015=100 index. All 18 mapped datasets returned data for all geos with no geo/time filter (≤ 2 000 cells each).

Geo codes (une_rt_a 2024): EU27_2020, EA21 (from 2026), EA20, BE, BG, CZ, DK, DE, EE, IE, EL, ES, FR, HR, IT, CY, LV, LT, LU, HU, MT, NL, AT, PL, PT, RO, SI, SK, FI, SE, IS, NO, CH, BA, ME, MK, RS, TR. Map to ISO2: EL→GR, UK→GB (UK present in some datasets but no values after 2020: geo=UK on une_rt_a → 0 values), everything else identical. Aggregates: EU27_2020, EA20, EA21, EU28 — drop or map to your own aggregate ids. Alternate SDMX 2.1 endpoint for CSV: …/api/dissemination/sdmx/2.1/data/{ds}/{key}?format=SDMX-CSV (header DATAFLOW,LAST UPDATE,freq,…,TIME_PERIOD,OBS_VALUE,OBS_FLAG).


# 5. WHO GHO OData — VERIFIED

Base https://ghoapi.azureedge.net/api/, OData v4 ($filter, $select, $top, $orderby; URL-encode spaces as %20). No key. cache-control: public, max-age=3600. Licence CC BY-NC-SA 3.0 IGO (cite "WHO Global Health Observatory").

  • GET /Indicator → 3 099 rows {"IndicatorCode":"WHOSIS_000001","IndicatorName":"Life expectancy at birth (years)","Language":"EN"}; search: /Indicator?$filter=contains(IndicatorName,'obesity').
  • Dimensions: /DIMENSION/SEX/DimensionValues → SEX_BTSX Both, SEX_FMLE, SEX_MLE, SEX_NOA; /DIMENSION/COUNTRY/DimensionValues → 234 with ParentCode = WHO region (AMR…).
  • Data row (/WHOSIS_000001?$filter=SpatialDim eq 'CAN' and Dim1 eq 'SEX_BTSX' and TimeDim ge 2019):
json
{"IndicatorCode":"WHOSIS_000001","SpatialDimType":"COUNTRY","SpatialDim":"CAN","ParentLocationCode":"AMR","ParentLocation":"Americas",
 "TimeDimType":"YEAR","TimeDim":2021,"Dim1Type":"SEX","Dim1":"SEX_BTSX","Dim2Type":null,"Dim2":null,
 "Value":"81.6 [81.5-81.7]","NumericValue":81.58276248,"Low":81.52940857,"High":81.68435338,"Date":"2024-08-02T09:43:39.193+02:00"}
  • SpatialDimType ∈ COUNTRY | REGION (AFR, AMR, EMR, EUR, SEAR, WPR) | GLOBAL | WORLDBANKINCOMEGROUP — filter SpatialDimType eq 'COUNTRY'. SpatialDim = ISO3. TimeDim = int year. Use NumericValue (the Value string embeds CIs). Date = row last modified (freshness).
Indicator Code Dim1 / Dim2 to filter CAN latest
Life expectancy WHOSIS_000001 Dim1 eq 'SEX_BTSX' 2021 81.6 (4 312 rows all sexes=BTSX)
Healthy life expectancy WHOSIS_000002 SEX_BTSX 2021 69.8
Adult obesity (age-std) NCD_BMI_30A SEX_BTSX, Dim2 AGEGROUP_YEARS18-PLUS 2024 26.0 %
Tobacco use M_Est_tob_curr SEX_BTSX contains projections to 2030 (2030: 8.3 %) — cap at ≤ current year
Medical doctors /10 000 HWF_0001 none 2024 28.54
Measles MCV1 WHS8_110 (WHS4_100 is DTP3, not measles) none 2025 92 %
Suicide rate SDGSUICIDE SEX_BTSX, Dim2 AGEGROUP_YEARSALL 2021
Infant mortality MDG_0000000001 SEX_BTSX, Dim2 AGEGROUP_MONTHS0-11 2024 4.7
Health exp. % GDP GHED_CHEGDP_SHA2011 none 2023 11.19
Safely managed water WSH_WATER_SAFELY_MANAGED Dim1 RESIDENCEAREATYPE_TOTL 2024 96.9
Alcohol per capita SA_0000001688 SEX_BTSX 2024 9.24 L

# 6. FRED — VERIFIED

Base https://api.stlouisfed.org/fred/, api_key=<FRED_API_KEY>&file_type=json. Limit 120 requests/minute (documented); observed: a burst of 130 parallel calls → 60×200, 23×429, 47×403 Akamai "Access Denied" and the 403 ban lasted several minutes for all series endpoints. Throttle to ≤ 2 req/s sequential. Licence: FRED terms; third-party series (BIS, OECD, S&P) keep their own terms.

GET /series/observations?series_id=FEDFUNDS&api_key=…&file_type=json&observation_start=2026-01-01 →

json
{"realtime_start":"2026-09-03","observation_start":"2026-01-01","units":"lin","output_type":1,"count":8,
 "observations":[{"realtime_start":"2026-09-03","realtime_end":"2026-09-03","date":"2026-08-01","value":"3.63"}]}
  • Values are strings; missing = "." (e.g. DGS10 on 2026-09-07 holiday). Params: frequency=a|q|m|w|d with aggregation_method=avg|sum|eop (tested: FEDFUNDS annual avg 2024 5.14, 2025 4.21, 2026 "." incomplete year), units=pc1|pch|lin…, observation_start/end, limit, sort_order.
  • GET /series?series_id=X → seriess[0] with title, frequency_short, units_short, observation_start, observation_end, last_updated, seasonal_adjustment_short, notes. Quirk: notes may contain raw control characters → strict JSON parsers (jq) fail; use a lenient parser (Python json.JSONDecoder(strict=False)).
  • Search: /series/search?search_text=…&limit=1000; /release/series?release_id=….

US series — all 30 exist (obs end / last update): CPIAUCSL (2026-07), UNRATE (2026-08), GDPC1 & GDP (2026-Q2), FEDFUNDS (2026-08), MORTGAGE30US (2026-09-10, W), CSUSHPINSA (2026-06, now titled "S&P Cotality Case-Shiller"), HOUST, PERMIT (2026-07), RHORUSQ156N (2026-Q2), MEHOINUSA672N (A, 2024), CIVPART, AHETPI, CES0500000003 (2026-08), GFDEGDQ188S (2026-Q1), DGS10 (D), DEXCAUS, DEXUSEU, DEXJPUS (D, 2026-09-04), T10Y2Y, PAYEMS, PCEPILFE, INDPRO, RSAFS, UMCSENT (2026-07), TOTALSA, PSAVERT, M2SL (2026-07), WALCL (W), BOPGSTB (2026-07).

International series (all exist):

  • BIS house prices: Q<ISO2>R628BIS real / Q<ISO2>N628BIS nominal, Index 2010=100, quarterly — verified CA, US, FR, DE, JP, GB, AU, ES, IT, KR, NZ, SE, CH (obs end 2026-Q1, JP 2025-Q4; updated 2026-06/08). 61 Q..R628BIS series found via search. (QCAN628BIS = nominal Canada.)
  • OECD MEI-derived (still present, but CPI ones discontinued at 2025-03): IRSTCI01CAM156N (CA immediate rate, to 2026-06), IR3TIB01CAM156N, IRLTLT01CAM156N, IRLTLT01DEM156N (10-y yields, 2026-06), LRHUTTTTCAM156S (CA unemployment, 2026-07), LRHUTTTTDEM156S, LRHUTTTTGBM156S, NAEXKP01CAQ657S (CA real GDP q/q, 2026-Q2), CLVMNACSCAB1GQDE (Eurostat DE real GDP, 2026-Q2). Stale: CPALTT01CAM659N, CPALTT01DEM659N, CPHPTT01GBM659N end 2025-03; CPALTT01JPM659N ends 2021-06. Prefer OECD/Eurostat/WB for non-US CPI.

# 7. Our World in Data — VERIFIED (CC BY 4.0; cite "Our World in Data" + underlying source from metadata)

File Size Rows × cols Years Notes
https://raw.githubusercontent.com/owid/co2-data/master/owid-co2-data.csv 14.4 MB 50 411 × 79 1750–2024 codebook owid-co2-codebook.csv (200)
https://raw.githubusercontent.com/owid/energy-data/master/owid-energy-data.csv 9.2 MB 23 377 × 130 1900–2025 codebook owid-energy-codebook.csv (200)
  • Key columns country,year,iso_code,population,gdp. Aggregates/regions have an empty iso_code (co2: 36 of 254 entities, e.g. World, Europe, European Union (27), High-income countries, Asia (GCP), International aviation, Kuwaiti Oil Fires; energy: 94 of 314 incl. Africa (EI), EU (Ember), historical Czechoslovakia, East Germany). No OWID_ codes in these two CSVs (unlike the grapher API) — also Kosovo has empty iso_code. Filter iso_code != "" for countries (then map OWID_KOS→XKX yourself if you take Kosovo from grapher).
  • All requested co2 columns exist: co2, co2_per_capita, co2_per_gdp, methane, nitrous_oxide, total_ghg, share_global_co2, temperature_change_from_co2, consumption_co2_per_capita, coal_co2, oil_co2, gas_co2, cumulative_co2, land_use_change_co2 (+ co2_including_luc, cement_co2, flaring_co2, trade_co2_share…). CAN 2024: co2 533.34 Mt, co2_per_capita 13.42, total_ghg 802.7, methane 115.3, land_use_change_co2 111.9, consumption_co2_per_capita empty for 2024 (lags a year).
  • All requested energy columns exist: electricity_generation, renewables_share_elec, solar_share_elec, wind_share_elec, hydro_share_elec, nuclear_share_elec, fossil_share_elec, low_carbon_share_elec, energy_per_capita, energy_per_gdp, primary_energy_consumption, per_capita_electricity, net_elec_imports_share_demand, carbon_intensity_elec. CAN 2025: generation 652.4 TWh, renewables 63.9 %, hydro 52.8 %, nuclear 13.1 %, fossil 23.0 %, per_capita_electricity 16 259 kWh, carbon_intensity_elec 190.7 gCO2/kWh; energy_per_capita empty for 2025 (Energy Institute data lags Ember).
  • Missing values = empty string. Units per codebook (co2 in Mt; shares in %; energy_per_capita kWh/person).

Grapher API: https://ourworldindata.org/grapher/life-expectancy.csv?v=1&csvType=full&useColumnShortNames=true → 605 KB, header entity,code,year,life_expectancy_0; 21 564 rows; aggregates carry OWID_ codes (OWID_WRL, OWID_EUR, OWID_HIC, OWID_KOS, OWID_USS…, 765 rows). csvType=filtered&country=CAN~USA&time=2020..latest works (Canada,CAN,2022,81.2493). Sibling ….metadata.json?… → {"chart":{"title","citation":"Riley (2005); Zijdeman et al. (2015); HMD (2025); UN WPP (2024)"},"columns":{"life_expectancy_0":{"titleShort","unit":"years","lastUpdated":"2025-10-22","citationShort":…}}} — use columns.*.lastUpdated for freshness and citationShort for attribution.


# 8. UN and others

UN WPP Data Portal API (https://population.un.org/dataportalapi/api/v1/): metadata endpoints /indicators, /locations answer 200 without a token, but every data endpoint (/data/indicators/49/locations/124/start/2023/end/2024) → HTTP 401, www-authenticate: Bearer — token required (confirmed). Token-free fallback: bulk CSV https://population.un.org/wpp/assets/Excel%20Files/1_Indicator%20(Standard)/CSV_FILES/WPP2024_Demographic_Indicators_Medium.csv.gz (200, 16.6 MB gz, includes ISO3 + projections to 2100).

UN Comtrade: https://comtradeapi.un.org/data/v1/get/C/A/HS?reporterCode=124&period=2023&partnerCode=0&cmdCode=TOTAL&flowCode=X → 401 "missing subscription key" (confirmed). Free preview works without key: https://comtradeapi.un.org/public/v1/preview/C/A/HS?reporterCode=124&period=2023&partnerCode=0&cmdCode=TOTAL&flowCode=X → {"count":12,"data":[{"period":"2023","flowCode":"X","cmdCode":"TOTAL","primaryValue":224462800586.53,…}]} (≤ 500 records, reporterISO null in preview, M49 numeric codes; rate-limited).

BIS Data Portal SDMX v2 (https://stats.bis.org/api/v2/, no key). CSV via ?format=csv; JSON needs header Accept: application/vnd.sdmx.data+json (format=json → 406). Country dim ISO2 (CA, US, XM euro area, 4T/5R/XW aggregates). Structures: /structure/dataflow/BIS/WS_CBPOL/1.0?references=all (Accept: application/vnd.sdmx.structure+json).

  • Policy rates WS_CBPOL, key FREQ.REF_AREA: GET /data/dataflow/BIS/WS_CBPOL/1.0/M.CA+US?startPeriod=2026-06&format=csv → FREQ,REF_AREA,UNIT_MEASURE,…,TIME_PERIOD,OBS_VALUE,OBS_STATUS → M,CA,368,…,2026-08,2.25,A / M,US,368,…,2026-08,3.625,A (unit 368 = per cent per year; US = midpoint of target range). All countries: /M.?startPeriod=2026-08 → 34 areas (AU BR CA CH CL CN CO CZ DK GB HK HU ID IS JP KW MA MK MX MY NO NZ PE PH PL RO RS RU SE TH TR US XM ZA). Daily also available (D.).
  • Property prices WS_SPP, key FREQ.REF_AREA.VALUE.UNIT_MEASURE (VALUE N nominal / R real; UNIT 628 index 2010=100, 771 y/y %): GET /data/dataflow/BIS/WS_SPP/1.0/Q.CA+US.R.628?startPeriod=2025-Q1&format=csv → Q,US,R,628,…,2025-Q1,159.7398,A. All countries latest: /Q..N+R.628?startPeriod=2026-Q1 → 59 areas, 118 rows. Quoted TITLE/COMPILATION fields contain commas — use a real CSV parser.

ILOSTAT SDMX (https://sdmx.ilo.org/rest/, no key, cache-control: no-store). The id DF_UNE_DEAP_SEX_AGE_RT_A does not exist (404 "Could not find Dataflow"); current flows (from /dataflow/ILO, 1 212 flows): DF_UNE_DEAP_SEX_AGE_RT (survey-based, annual+quarterly) and DF_UNE_2EAP_SEX_AGE_RT ("ILO modelled estimates, Nov. 2025", incl. projections). Dims REF_AREA.FREQ.MEASURE.SEX.AGE. GET /data/ILO,DF_UNE_DEAP_SEX_AGE_RT/.A..SEX_T.AGE_YTHADULT_YGE15?startPeriod=2024&format=csv → 537 rows, 200 areas: DATAFLOW,REF_AREA,FREQ,MEASURE,SEX,AGE,TIME_PERIOD,OBS_VALUE,OBS_STATUS,…,SOURCE → ILO:DF_UNE_DEAP_SEX_AGE_RT(1.0),CAN,A,UNE_DEAP_RT,SEX_T,AGE_YTHADULT_YGE15,2023,5.389,,RT,PT,0,LFS - Labour Force Survey,…. Modelled: /data/ILO,DF_UNE_2EAP_SEX_AGE_RT/.A..SEX_T.AGE_YTHADULT_YGE15?startPeriod=2025 → 271 areas, years 2025–2027 (2026–2027 are projections; CAN 2025 6.907 = WB SL.UEM.TOTL.ZS 2025). Age codes: AGE_YTHADULT_YGE15 (15+), AGE_YTHADULT_Y15-64, AGE_YTHADULT_Y15-24 youth.


# Cross-source notes for connectors

  • Prefer ISO3 as the canonical key. Convert: Eurostat EL→GR, UK→GB (ISO2→ISO3 table); BIS ISO2→ISO3; OWID OWID_KOS→XKX, drop other OWID_*; WB XKX Kosovo exists; IMF uses KOS; WHO uses ISO3 but no Kosovo.
  • Forecast flags: IMF TIME_PERIOD > LATEST_ACTUAL_ANNUAL_DATA; ILO modelled year > 2025; WHO tobacco has 2030 values; Eurostat status p/e; FRED incomplete-year aggregates return ".".
  • Freshness fields: WB lastupdated (meta) and /source/2.lastupdated; IMF CSV UPDATE_DATE; OECD none per row (HTTP last-modified absent) → store fetch date; Eurostat updated; WHO Date; FRED last_updated; OWID metadata columns.*.lastUpdated, GitHub etag.
  • Parsing hazards: WB empty countryiso3code for 5 income aggregates; FRED control chars in notes; OECD/BIS labels with commas; OECD jsondata descending time; Eurostat sparse index arithmetic.