{"openapi":"3.1.0","info":{"title":"Unmapped Labs API","version":"v1","description":"South African datasets, checked against their sources. Records come a page at a time, within a daily records limit per account (see the X-Daily-* headers). Changes within v1 only add things: fields and endpoints aren't removed or renamed without notice. Docs: https://unmapped.co.za/docs","contact":{"email":"hello@unmappedlabs.com","url":"https://unmapped.co.za/docs"},"termsOfService":"https://unmapped.co.za/terms"},"servers":[{"url":"https://api.unmappedlabs.com/v1"}],"security":[{"bearer":[]}],"paths":{"/datasets":{"get":{"summary":"Every dataset, and whether it's switched on and available","operationId":"listDatasets","responses":{"200":{"description":"The datasets"},"400":{"description":"A parameter isn't valid; the message says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No key, or not a valid one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"A paid dataset not bought","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The dataset isn't switched on for the account, or the terms aren't accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dataset has no records yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests a minute, or the daily records limit is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/datasets/{id}":{"get":{"summary":"One dataset: its fields, filters and live release","operationId":"getDataset","parameters":[{"name":"id","in":"path","required":true,"description":"Dataset id","schema":{"type":"string","enum":["dam-levels","electricity-tariffs","reference-rates","reserve-bank-series"]}}],"responses":{"200":{"description":"The dataset"},"400":{"description":"A parameter isn't valid; the message says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No key, or not a valid one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"A paid dataset not bought","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The dataset isn't switched on for the account, or the terms aren't accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dataset has no records yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests a minute, or the daily records limit is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/datasets/{id}/records":{"get":{"summary":"Records, filtered and a page at a time","operationId":"listRecords","parameters":[{"name":"id","in":"path","required":true,"description":"Dataset id","schema":{"type":"string","enum":["dam-levels","electricity-tariffs","reference-rates","reserve-bank-series"]}},{"name":"from","in":"query","required":false,"description":"Only records on or after this date (the dataset's own date field)","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Only records on or before this date","schema":{"type":"string","format":"date"}},{"name":"station","in":"query","required":false,"description":"Filter, for dam-levels: DWS station code of a dam (e.g. D3R002)","schema":{"type":"string"}},{"name":"province","in":"query","required":false,"description":"Filter, for dam-levels: Province code, ISO 3166-2 (e.g. ZA-WC)","schema":{"type":"string"}},{"name":"country","in":"query","required":false,"description":"Filter, for dam-levels: ZA, or LS and SZ for the Lesotho and Eswatini dams (e.g. ZA)","schema":{"type":"string"}},{"name":"river","in":"query","required":false,"description":"Filter, for dam-levels: River, as DWS names it (e.g. Orange River)","schema":{"type":"string"}},{"name":"distributor","in":"query","required":false,"description":"Filter, for electricity-tariffs: Municipal Demarcation Board code of the distributor (e.g. CPT)","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Filter, for electricity-tariffs: Tariff category: residential, commercial, large_power, embedded_generation, wheeling, generator or public_lighting (e.g. residential)","schema":{"type":"string"}},{"name":"financial_year","in":"query","required":false,"description":"Filter, for electricity-tariffs: Municipal financial year (e.g. 2026/27)","schema":{"type":"string"}},{"name":"rate","in":"query","required":false,"description":"Filter, for reference-rates: policy_rate (the repo rate), prime_lending_rate, zaronia or sabor (e.g. prime_lending_rate)","schema":{"type":"string"}},{"name":"currency","in":"query","required":false,"description":"Filter, for reserve-bank-series: USD, GBP, EUR, JPY, or NEER for the nominal effective exchange rate (e.g. USD)","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"json (the default) or csv","schema":{"type":"string","enum":["json","csv"]}},{"name":"limit","in":"query","required":false,"description":"Records per page (JSON up to 100, CSV up to 1,000)","schema":{"type":"integer","minimum":1}},{"name":"cursor","in":"query","required":false,"description":"From the previous page's next link; stays on the release it started on","schema":{"type":"string"}},{"name":"key","in":"query","required":false,"description":"Your key, for CSV only (spreadsheets that can't send headers)","schema":{"type":"string"}}],"security":[{"bearer":[]},{"keyInQuery":[]}],"responses":{"200":{"description":"A page of records","headers":{"X-Daily-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"dataset":{"type":"string"},"version":{"type":"string"},"count":{"type":"integer"},"offset":{"type":"integer"},"returned":{"type":"integer"},"records":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/DamLevels"},{"$ref":"#/components/schemas/ElectricityTariffs"},{"$ref":"#/components/schemas/ReferenceRates"},{"$ref":"#/components/schemas/ReserveBankSeries"}]}},"next":{"type":["string","null"]}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A parameter isn't valid; the message says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No key, or not a valid one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"A paid dataset not bought","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The dataset isn't switched on for the account, or the terms aren't accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dataset has no records yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests a minute, or the daily records limit is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/datasets/{id}/latest":{"get":{"summary":"The newest record for each currency, rate, dam or tariff","operationId":"latestRecords","parameters":[{"name":"id","in":"path","required":true,"description":"Dataset id","schema":{"type":"string","enum":["dam-levels","electricity-tariffs","reference-rates","reserve-bank-series"]}},{"name":"from","in":"query","required":false,"description":"Only records on or after this date (the dataset's own date field)","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Only records on or before this date","schema":{"type":"string","format":"date"}},{"name":"station","in":"query","required":false,"description":"Filter, for dam-levels: DWS station code of a dam (e.g. D3R002)","schema":{"type":"string"}},{"name":"province","in":"query","required":false,"description":"Filter, for dam-levels: Province code, ISO 3166-2 (e.g. ZA-WC)","schema":{"type":"string"}},{"name":"country","in":"query","required":false,"description":"Filter, for dam-levels: ZA, or LS and SZ for the Lesotho and Eswatini dams (e.g. ZA)","schema":{"type":"string"}},{"name":"river","in":"query","required":false,"description":"Filter, for dam-levels: River, as DWS names it (e.g. Orange River)","schema":{"type":"string"}},{"name":"distributor","in":"query","required":false,"description":"Filter, for electricity-tariffs: Municipal Demarcation Board code of the distributor (e.g. CPT)","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Filter, for electricity-tariffs: Tariff category: residential, commercial, large_power, embedded_generation, wheeling, generator or public_lighting (e.g. residential)","schema":{"type":"string"}},{"name":"financial_year","in":"query","required":false,"description":"Filter, for electricity-tariffs: Municipal financial year (e.g. 2026/27)","schema":{"type":"string"}},{"name":"rate","in":"query","required":false,"description":"Filter, for reference-rates: policy_rate (the repo rate), prime_lending_rate, zaronia or sabor (e.g. prime_lending_rate)","schema":{"type":"string"}},{"name":"currency","in":"query","required":false,"description":"Filter, for reserve-bank-series: USD, GBP, EUR, JPY, or NEER for the nominal effective exchange rate (e.g. USD)","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"json (the default) or csv","schema":{"type":"string","enum":["json","csv"]}},{"name":"key","in":"query","required":false,"description":"Your key, for CSV only","schema":{"type":"string"}}],"security":[{"bearer":[]},{"keyInQuery":[]}],"responses":{"200":{"description":"The latest records","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/DamLevels"},{"$ref":"#/components/schemas/ElectricityTariffs"},{"$ref":"#/components/schemas/ReferenceRates"},{"$ref":"#/components/schemas/ReserveBankSeries"}]}}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A parameter isn't valid; the message says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No key, or not a valid one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"A paid dataset not bought","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The dataset isn't switched on for the account, or the terms aren't accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dataset has no records yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests a minute, or the daily records limit is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/datasets/{id}/releases":{"get":{"summary":"What changed in each release: the changelog","operationId":"listReleases","parameters":[{"name":"id","in":"path","required":true,"description":"Dataset id","schema":{"type":"string","enum":["dam-levels","electricity-tariffs","reference-rates","reserve-bank-series"]}}],"responses":{"200":{"description":"Releases, newest first"},"400":{"description":"A parameter isn't valid; the message says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No key, or not a valid one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"A paid dataset not bought","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The dataset isn't switched on for the account, or the terms aren't accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dataset has no records yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests a minute, or the daily records limit is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Your key from app.unmappedlabs.com: Authorization: Bearer um_live_…"},"keyInQuery":{"type":"apiKey","in":"query","name":"key","description":"CSV only, for spreadsheets. Use a key made for the purpose; revoke it if the link is shared."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}},"DamLevels":{"type":"object","title":"Dam levels with full history","description":"One record per dam, per weekly State of Dams report","properties":{"id":{"type":"string","description":"Station code and report date (D3R002-2026-10-26)"},"station":{"type":"string","description":"The Department of Water and Sanitation's station code for the dam; stable from week to week"},"dam":{"type":"string","description":"Dam name as DWS gives it"},"river":{"type":"string","description":"River the dam is on"},"country":{"type":"string","description":"ZA, or LS and SZ for the Lesotho and Eswatini dams that supply South Africa"},"provinces":{"type":"array","description":"Province codes, ISO 3166-2 (ZA-FS); two where a dam sits on a provincial border"},"report_date":{"type":"string","format":"date","description":"Date of the weekly report"},"full_supply_capacity":{"type":"number","description":"Full supply capacity, in million cubic metres"},"percent_full":{"type":"number","description":"Storage as a % of full supply capacity this week; above 100 when the dam is over full supply"},"percent_full_last_week":{"type":"number","description":"The same, a week earlier"},"percent_full_last_year":{"type":"number","description":"The same, a year earlier"},"volume":{"type":"number","description":"Water stored, in million cubic metres: capacity × % full, worked out by us"},"flags":{"type":"array","description":"not_this_week (DWS shows its latest available reading, not this week's) and above_full_supply"},"source":{"type":"object","description":"Publisher, report and the DWS page the figures come from"}}},"ElectricityTariffs":{"type":"object","title":"Municipal electricity tariffs","description":"One record per tariff, per distributor, per financial year","properties":{"id":{"type":"string","description":"Stable id: country, distributor, tariff and financial year"},"distributor":{"type":"string","description":"Licensed distributor: Eskom or the municipality"},"distributor_code":{"type":"string","description":"Municipal Demarcation Board code of the municipality (CPT, ETH)"},"tariff":{"type":"string","description":"Tariff name as the decision gives it"},"category":{"type":"string","description":"residential, commercial, large_power, agricultural, embedded_generation, wheeling, generator, public_lighting or other"},"financial_year":{"type":"string","description":"Municipal financial year, July to June"},"effective_from":{"type":"string","format":"date","description":"Date the tariff takes effect"},"status":{"type":"string","description":"Where the tariff is in NERSA's approval process"},"charges":{"type":"array","description":"Each charge: name, season (high_demand is winter, usually June to August), time-of-use period, meter, kWh block, unit, the approved value, last year's approved value (previous) and, where the decision shows it, what was actually charged last year (previous_charged)"},"vat":{"type":"string","description":"Whether the charges include VAT, as the source states it"},"source":{"type":"object","description":"Publisher, document, decision date, page and link"},"flags":{"type":"array","description":"Machine-readable notes from checking: summary_rate_differs, suspect_value_in_source, obsolete_tariff, unit_not_stated"},"notes":{"type":"array","description":"What each flag means for this record, in words"}}},"ReferenceRates":{"type":"object","title":"Reference interest rates and legal limits","description":"One record per rate, per date it took a new value","properties":{"id":{"type":"string","description":"Rate and effective date (policy-rate-2026-09-19)"},"rate":{"type":"string","description":"policy_rate (the repo rate), prime_lending_rate, zaronia or sabor"},"name":{"type":"string","description":"The rate's full name"},"effective_from":{"type":"string","format":"date","description":"First day the rate had this value, as the Reserve Bank's series shows it"},"value":{"type":"number","description":"The rate, % a year"},"previous":{"type":"number","description":"The value before this one, % a year"},"change":{"type":"number","description":"Change from the previous value, in percentage points"},"series_code":{"type":"string","description":"The Reserve Bank's time series code (MMRD002A)"},"flags":{"type":"array","description":"first_in_series, and spread_not_3_5 where prime isn't the policy rate plus 3.5 points"},"source":{"type":"object","description":"Publisher, series and the API address it came from"}}},"ReserveBankSeries":{"type":"object","title":"Reserve Bank statistical series","description":"One record per currency per business day","properties":{"id":{"type":"string","description":"Currency and date (usd-2026-10-30)"},"currency":{"type":"string","description":"USD, GBP, EUR or JPY (ISO 4217), or NEER for the nominal effective exchange rate of the rand"},"name":{"type":"string","description":"The currency's or the index's name"},"date":{"type":"string","format":"date","description":"Business day of the rate, as the Reserve Bank's series shows it"},"value":{"type":"number","description":"Rand per one unit of the currency, the weighted average of the banks' rates at about 10:30 (the yen too: rand per one yen, to four decimals); for NEER the index, where higher means a stronger rand"},"unit":{"type":"string","description":"Rand per US dollar, British pound, euro or Japanese yen, or the index and its base year (Index, 2022 = 100)"},"series_code":{"type":"string","description":"The Reserve Bank's time series code (EXCX135D)"},"flags":{"type":"array","description":"large_move (4% or more from the series' previous value), after_gap (no value on the business day before, though the other series have one) and suspect_value_in_source (far from both neighbouring days, published as SARB shows it)"},"source":{"type":"object","description":"Publisher, series and the API address it came from"}}}}}}