AdvocacyAPI — Data Overview

Current Database

1,807,072
Postcodes
10,506
Areas
20,258
Active Representatives
5,653
With Email
of 20,258 reps
155
Political Parties

Representatives by Source

Source Active Reps With Email
local_councillors 19,266 4,665 (24.2%)
mayors 27 27 (100.0%)
ni_assembly 90 89 (98.9%)
scottish_parliament 129 129 (100.0%)
senedd 96 96 (100.0%)
uk_parliament 650 647 (99.5%)

Recent Syncs

Loader Status Completed
uk_parliament success 2026-11-01 06:01:02
london_assembly failed 2026-11-01 06:00:53
london_assembly failed 2026-11-01 06:00:34
london_assembly failed 2026-11-01 06:00:17
mayors success 2026-11-01 06:00:17

Data Sources & Coverage

Representatives

Type Source Records Coverage Status
UK Parliament MPs members-api.parliament.uk 650 All of England, Wales, Scotland, NI Implemented
  └ Emails Same API (/Members/{id}/Contact) 650 100% — firstname.lastname.mp@parliament.uk Not yet fetched
  └ Photos Same API (thumbnailUrl field) 650 100% Stored in metadata
Scottish Parliament MSPs data.parliament.scot OData ~129 All constituency + regional MSPs Implemented
  └ Emails Same API (/api/emailaddresses) ~129 100% — firstname.lastname.msp@parliament.scot Not yet fetched
  └ Photos Same API (PhotoURL field) ~129 Most Stored in metadata
Local Councillors opencouncildata.co.uk CSV ~19,300 384 councils across UK Implemented
  └ Emails Modern.gov council portals (scraping) est. ~10,000 ~200 councils (~50%) — see below PoC built
  └ Emails CMIS council portals (scraping) est. ~1,500 ~21 councils — see below PoC built
Senedd (Welsh) Members data.senedd.wales or scrape 60 All of Wales Not implemented
NI Assembly MLAs data.niassembly.gov.uk SOAP/XML 90 All of Northern Ireland Not implemented
London Assembly Members london.gov.uk 25 14 constituency + 11 London-wide Not implemented

Postcode Mapping

Area Type Source Records Mapping Status
Westminster constituencies postcodes.io pg_dump 650 postcodes.constituency_id → constituencies Imported
Scottish Parliament constituencies postcodes.io pg_dump 73 scottish_postcodes.scottish_constituency_id → scottish_constituencies Imported
Wards postcodes.io pg_dump ~8,400 postcodes.admin_ward_id → wards Imported
Local authorities postcodes.io pg_dump ~360 postcodes.admin_district_id → districts Imported
Senedd constituencies Boundary data / Electoral Commission 48 Needs supplementary postcode mapping Not imported
NI Assembly constituencies EONI / boundary data 18 Needs supplementary postcode mapping Not imported
London Assembly constituencies GLA boundary data 14 Needs supplementary postcode mapping Not imported

Council Spending

Dataset Source Records Coverage Status
Creditor payments (over £250) Brighton & Hove monthly CSVs 52 monthly files, April 2022 – July 2026, no gaps Brighton and Hove only — 1 of 384 councils Implemented; the 3 earlier quarterly files are not loadable, and Oct–Dec 2021 was never published — see below
Contracts register Brighton & Hove In-tend portal 1,734 rows / 1,732 contracts, one GET Brighton and Hove only — 1 of 384 councils Implemented — see below
Contract award notices Contracts Finder (OCDS) 99 for Brighton National, ~£25k and up Implemented; monthly windows on ingest_windows

Councillor Email Coverage (Modern.gov)

~200 UK councils use the Civica Modern.gov platform for their democracy portals. These expose a mailing list endpoint (/mgCommitteeMailingList.aspx?EM=1&ID=0) that lists all councillor names and emails as CSV-formatted text.

Two URL patterns:

Verified working

Council Modern.gov URL Councillors Emails
Brighton and Hove democracy.brighton-hove.gov.uk 54 53
Doncaster doncaster.moderngov.co.uk 60 55
Barnet barnet.moderngov.co.uk 63 63
Bristol bristol.moderngov.co.uk - -
Cardiff cardiff.moderngov.co.uk - -
Sheffield democracy.sheffield.gov.uk - -
Manchester democracy.manchester.gov.uk - -
Cornwall democracy.cornwall.gov.uk - -
Durham democracy.durham.gov.uk - -
Blackpool democracy.blackpool.gov.uk - -
Buckinghamshire buckinghamshire.moderngov.co.uk - -
Bolton bolton.moderngov.co.uk - -
Bradford bradford.moderngov.co.uk - -

Councils not using Modern.gov

Some councils use other platforms where a different scraping strategy would be needed:

Platform Example Notes
CMIS Birmingham (birmingham.cmis.uk.com) Implemented — see below
Bespoke / in-house Liverpool Would need per-council scrapers
Scottish councils Aberdeen, Angus, Argyll and Bute Many use different systems
NI councils Belfast, Antrim Use NI-specific systems

Scaling approach

The enricher at lib/advocacy_api/enrichers/moderngov.ex maps council names (as they appear in the Open Council Data CSV) to their Modern.gov base URL. Adding a council is one line:

@council_urls %{
  "Brighton and Hove" => "https://democracy.brighton-hove.gov.uk",
  "Doncaster" => "https://doncaster.moderngov.co.uk",
  # add more here...
}

Name matching between Open Council Data and Modern.gov is near-perfect — tested with Brighton and Hove where 53/53 names matched exactly (only the “Vacant” seat was unmatched).

To build out the full mapping, the URL slug can often be guessed from the council name, but not always (e.g., “Brighton and Hove” → brighton-hove, “South Cambridgeshire” → scambs). A manual mapping or a discovery script that tries both URL patterns would be the next step.

Councillor Email Coverage (CMIS)

~60 UK councils use CMIS by Astech Consultants for their democracy portals. Unlike Modern.gov (which exposes a single mailing-list endpoint), CMIS requires a two-step scrape: first fetch the councillors list page to discover individual councillor URLs, then visit each detail page to extract the email address.

The enricher at lib/advocacy_api/enrichers/cmis.ex handles this automatically with concurrent detail-page fetching.

Three URL patterns:

Scaling approach

Adding a council requires one line in the @council_urls map:

@council_urls %{
  "Birmingham" => "https://birmingham.cmis.uk.com/birmingham/Councillors.aspx",
  "Dudley" => "https://dudley.cmis.uk.com/Councillors.aspx",
  # add more here...
}

The council name must match exactly what appears in the Open Council Data CSV. The scraper visits each councillor’s detail page concurrently (4 at a time) so enrichment takes longer than Modern.gov but is still practical.

Area-Level Datasets

The API attaches statistical datasets to each postcode via its geography codes (LSOA, MSOA, constituency, local authority). Each dataset has typed headline columns for fast queries and a JSONB detail column for full breakdowns.

LSOA-Level Datasets (Lower Layer Super Output Areas)

LSOAs are small statistical areas of roughly 1,500 people / 650 households. England has 32,844 LSOAs. These provide the most granular neighbourhood-level data.

Dataset Source Date / Vintage Geography Coverage Key Fields Limitations
IMD 2019 MHCLG 2019 (based on 2015/16 data) LSOA 2011 England only Rank, decile across 7 domains Uses 2011 LSOA boundaries; last updated 2019; no Scotland/Wales/NI equivalent in this dataset
Census 2021 ONS / Nomis March 2021 LSOA 2021 England & Wales Population, households, median age, ethnicity, tenure, health, qualifications, economic activity, household composition, language Conducted during COVID — may not reflect normal patterns; Scotland ran Census 2022 separately (not included)
Fuel Poverty DESNZ 2022 estimates (published 2024) LSOA 2021 England only % fuel poor, number of fuel-poor households Modelled estimates using the Low Income Low Energy Efficiency (LILEE) definition; Scotland/Wales use different definitions
Benefits / Universal Credit DWP Stat-Xplore Rolling monthly (latest available) LSOA 2021 Great Britain UC claimants, claimant rate Counts suppressed where <10 to prevent identification; does not include legacy benefits still being migrated to UC
Crime data.police.uk Rolling 12 months LSOA 2011 England & Wales Total crimes, rate per 1,000, breakdown by category Location snapped to anonymous points (not exact); some forces have reporting delays; BTP crimes excluded from local counts
AHAH (Access to Healthy Assets & Hazards) CDRC v3 (2022) LSOA 2011 England & Wales Overall index, retail environment, health services, physical environment sub-indices Academic dataset — registration required; composite index may mask local variation in individual components
EPC (Energy Performance) DLUHC Open Data Cumulative (certificates from 2008+) Aggregated to LSOA England & Wales Median energy efficiency score, band distribution Only covers properties that have been sold/rented/built since 2008; older housing stock under-represented; self-selection bias
GP Registrations NHS Digital Quarterly LSOA 2021 England Patient count, practice breakdown Patients registered ≠ residents (students, commuters may register elsewhere); some practices span many LSOAs
Air Quality DEFRA NAEI 2022 modelled concentrations 1km grid → LSOA UK-wide NO₂ annual mean (µg/m³), PM2.5 annual mean (µg/m³) Modelled from 1km grid (not measured); may miss hyper-local pollution hotspots near roads; background concentrations only
Flood Risk Environment Agency / Friends of the Earth Based on EA flood maps (2023) LSOA 2011 England % properties at risk Fluvial and surface water risk only; does not include coastal or groundwater flooding; risk ≠ actual flooding history
Broadband Ofcom Connected Nations 2023 LSOA 2021 UK Average download/upload speed (Mbps) Averages mask variation within LSOA; based on ISP-reported data not speed tests; does not reflect actual user experience
Child Poverty End Child Poverty / DfE 2022/23 estimates LSOA 2021 England & Wales Child poverty rate (%), FSM eligibility (%) Modelled estimates (not direct counts); definitions of poverty vary between sources; FSM data is school-based not residential
House Prices ONS HPSSA Rolling year to latest quarter LSOA 2021 England & Wales Median price paid Based on Land Registry transactions only (not valuations); low-volume LSOAs may have unreliable medians; does not capture properties that haven’t sold recently

MSOA-Level Datasets (Middle Layer Super Output Areas)

MSOAs are larger areas of roughly 7,500 people. England has 6,791 MSOAs. Used for data that is too volatile at LSOA level.

Dataset Source Date / Vintage Coverage Key Fields Limitations
Life Expectancy ONS 2018–2020 (3-year pooled) England & Wales Life expectancy at birth (male/female), healthy life expectancy (male/female) 3-year pooled estimates needed for statistical reliability; pre-dates COVID impact; MSOA boundaries may not align with community boundaries

Constituency-Level Datasets

Dataset Source Date / Vintage Coverage Key Fields Limitations
2024 General Election Results House of Commons Library July 2024 All 650 UK constituencies Winner, majority, turnout, full party results New 2024 boundaries — historical comparison with pre-2024 results is not directly possible; by-election results not automatically updated

Local Authority-Level Datasets

Dataset Source Date / Vintage Coverage Key Fields Limitations
Life Expectancy ONS 2018–2020 UK Life expectancy at birth (male/female), healthy life expectancy Same pooling caveats as MSOA; LA boundaries changed in several reorganisations (2019–2023)
Population ONS Mid-Year Estimates 2023 UK Total population Based on Census 2021 rolled forward with births/deaths/migration estimates

NHS integrated care boards

Table: care_boards — ods_code, name, region, postcode_count, papers_collected.

Source: derived from the ONS Postcode Directory, not typed in. AdvocacyApi.CareBoards.refresh/0 reads the postcodes.io icb lookup table when the full dump has been imported (giving both code and name) and otherwise falls back to the distinct values on postcodes.icb.

What we hold: the bodies, and which postcodes and councils fall in each. This is what makes a postcode lookup return a care board.

What we do not hold: board membership, meeting dates, papers, minutes and decisions. papers_collected is false for every row, and every screen says so in words rather than rendering an empty table. Collecting them means scraping 42 separate websites and has not been built.

Caveat: before the directory backfill has run, postcodes.icb carries the ODS code rather than the resolved name, so a board can be stored with its code as its name. CareBoardHTML.title/1 labels that case as “Care board QNX” rather than presenting a code as a name.

Council spend (creditor payments)

Everything below was measured against Brighton and Hove on 8 September 2026. It is one council’s shape, not a national schema.

Source: the council publishes monthly creditor payment CSVs. The index page /payments-over-ps250 links one page per financial year, each of which links that year’s monthly files. 52 monthly files are published, April 2022 to July 2026 — every month in that range, with no gaps. Before that the council published quarterly, and only partly: there are files for April–June 2021, July–September 2021 and January–March 2022, and October–December 2021 is not published in any form. Licence: Open Government Licence v3.0.

data.gov.uk is not a way in. The entry for this dataset is a dead stub — “There are no links to this data” — despite being marked updated 8 July 2026. The council’s own pages are the only route.

The threshold is £250, not the statutory £500. Brighton dropped from £500 in April 2013, so the over-£500 register is a filter over this data rather than a separate publication. 52–55% of rows clear £500.

Shape: eight columns, stable across every month sampled (June 2025, January 2026, April 2026, July 2026 — 37,373 rows):

Creditor Name, Transaction Number, Date, Net Amount, Expenditure Summary, Category, Directorate, Section

8,200–10,700 rows and £43m–£64m per month, across ~1,300–1,400 distinct creditors.

Traps in the file

Traps in getting the file

Where the code lives

Council contracts register (Brighton)

Brighton publishes its own contracts register on its In-tend e-tendering portal. It holds 1,734 contracts against Contracts Finder’s 99 for the same council, because most council procurement is a framework call-off or a delegated award and neither generates a national notice. Three suppliers with no Contracts Finder notice at all appear here with a contract: FM Conway, Van Oord and Achieve together.

One public GET, no login, no paging: https://in-tendhost.co.uk/brightonandhove/aspx/ViewContractsRegister.aspx?id=dec104fe-f8cb-4735-90b4-bffa79ed9a82 — 2.1 MB of HTML holding one table of 1,735 rows.

Six columns, and six is all there is: Reference | Title | Suppliers | Extension Date | Expiry Date | Value. The table contains zero hrefs — there are no per-contract detail pages, only an ASP.NET postback into the same page — so there is nothing more to crawl.

Traps in the page

Not on the ingest_windows ledger

Unlike council spend. A window is a period, and this source has none — one URL returns the whole register as it stands. Filing it under invented months would fill the coverage matrix with green cells that all mean “we fetched the same page again”. A run is recorded in sync_logs instead.

Where the code lives

Staged Source Files

Every URL hard-coded in priv/scripts/import_*.exs had rotted (404/403) by September 2026. These are the replacements, re-verified, downloaded and staged in /opt/advocacy-api/priv/data/ on the VPS — a directory the deploy rsync excludes, so it survives deploys.

Almost none of them are CSV any more. They were converted with a stdlib zipfile/openpyxl/xlrd pass, taking the named sheet and skipping the gov.uk preamble rows; the Join column is the measured overlap against the codes actually in postcodes (not an estimate).

Staged file Source URL Original Sheet Geography Join
fuel_poverty.csv DESNZ sub-regional fuel poverty 2026 (2024 data) xlsx Table 4 LSOA 2021 33,755 / 33,756 (100%)
flood_risk.csv FoE flood risk & social vulnerability xlsx first LSOA 2011 31,809 / 32,843 (96.9%)
house_prices_lsoa.csv ONS HPSSA dataset 46 zip → xls 1a LSOA 2011 33,647 / 34,753 (96.8%)
broadband_oa.csv, _laua, _pcon Ofcom Connected Nations 2025 fixed performance zip → csv — OA 2021 238,861 / 238,864 (100%)
life_expectancy_{le,hle,dfle}_msoa.csv ONS health state LE for MSOAs, 2019–2023 xlsx 1,2,3 MSOA 2021 7,264 / 7,264 (100%)
ge2024_constituencies.csv electionresults.uk 2024 csv — 2024 constituencies 650 rows
crime/YYYY-MM/*-street.csv data.police.uk archive zip → csv — LSOA 2021 509 files, 12 months
child_poverty_{constituency,la}.csv End Child Poverty AHC 2024/25 xlsx 3,2 LA + constituency 650 / 361 rows

Notes on the replacements

Data Freshness

Dataset Update frequency Last imported
postcodes.io pg_dump Periodic — check latest for new releases 2025-12-18
Representatives Daily at 06:00 UTC via Oban cron Ongoing
Councillor emails On-demand via enricher (could be added to cron) On-demand
Council spend (Brighton) Monthly, published in arrears — the upload month is not the data month Walked via ingest_windows (council_spend)
Council contracts register (Brighton) Live page, no publication schedule — re-fetch and re-upsert On demand: Release.load_register/1
IMD 2019 Static (no new release planned) Import script: import_imd.exs
Census 2021 Static (next census ~2031) Import script: import_census.exs
Fuel Poverty Annual (typically spring) Import script: import_fuel_poverty.exs
Crime Monthly (bulk download) Import script: import_crime.exs
House Prices Quarterly Import script: import_house_prices.exs
Broadband Annual (autumn) Import script: import_broadband.exs
Election Results After each general election Import script: import_election_results.exs
Life Expectancy Biennial Import script: import_life_expectancy.exs
EPC Cumulative (certificates added daily) Import script: import_epc.exs
Child Poverty Annual Import script: import_child_poverty.exs
Flood Risk Irregular (when EA updates maps) Import script: import_flood_risk.exs

Key Limitations & Caveats

  1. England-centric: Most LSOA-level datasets cover England only (or England & Wales). Scotland and Northern Ireland publish equivalent data but using different geographies and definitions, which are not yet integrated.

  2. Boundary mismatches: IMD 2019 and some other datasets use 2011 LSOA boundaries, while Census 2021 introduced new 2021 LSOA boundaries. Most LSOAs are unchanged, but ~5% were split or merged. We join on LSOA code which handles this for matching LSOAs, but some 2011-only LSOAs may not match 2021 codes.

  3. Point-in-time snapshots: Most datasets are annual or less frequent snapshots. The API returns the most recently imported version — it does not track changes over time (except house prices which include historical data in the detail JSONB).

  4. Modelled vs measured: Several datasets (fuel poverty, child poverty, air quality) are modelled estimates, not direct measurements. They carry inherent uncertainty that increases at smaller geographies.

  5. Small area suppression: DWP benefits data suppresses counts below 10 to prevent identification. This means the most deprived areas (few claimants) may show as null rather than a small number.

  6. No real-time data: All datasets are retrospective. Crime data has a ~2 month lag, benefits data ~1 month, house prices ~3 months from transaction to publication.