The whole index is published as data, for journalists, researchers and anyone who wants to check it. There is no API and no key: these are static files served from the same place as the site. Read the methodology before drawing conclusions from them.
The files
| File | What it is |
|---|---|
data/alignment.json | The canonical output of pipeline/score.py. Never hand-edited. Everything the site shows is read from it. |
data/alignment.csv | The same figures flattened by pipeline/export.py: one row per member × industry pair, joined to the roster. Plain CSV, UTF-8 without a byte-order mark, one header row, no comment lines. |
politicians.json | The roster of 547 officials (House, Senate, President, Vice President, Supreme Court). Joins to the index on bioguide. |
alignment.json — schema
A single JSON object, written on one line. Floating-point values are rounded at write time; the rounding is stated per field below. A pair that falls below any coverage floor is absent, never present with a zero.
Top level
| Field | Type | Meaning |
|---|---|---|
updated_utc | string | When the scorer last ran, ISO 8601 UTC, e.g. 2026-09-22T16:13:21Z. Changes on every run, so it is ignored when deciding whether the data changed. |
method | string | Always peer-adjusted donor alignment residual. |
note | string | A one-paragraph plain-English statement of what the index measures and why there is no overall per-person score. |
thresholds | object | The coverage floors every published pair has cleared (below). |
sources | object | Map of upstream feed file name → the base URL (or local directory) it was read from. |
industries | object | Map of industry id → {label, sector}, carried through from the money feed so that labels are never hard-coded. Only industries with at least one published pair appear. |
members | object | Map of bioguide id → member record. Only members with at least one published pair appear; every other official is not measured. |
thresholds
| Field | Type | Meaning |
|---|---|---|
min_votes | integer | Fewest informative roll calls in the industry (currently 4). |
min_vote_coverage | number | Smallest sum of informativeness weights over those roll calls (currently 1.0). |
min_industry_dollars | integer | Smallest direct industry PAC money to the member, US dollars (currently 5000). |
min_peers | integer | Smallest number of eligible members in the peer group for that industry (currently 12). |
members[bioguide]
| Field | Type | Meaning |
|---|---|---|
peer_group | [string, string, string] | [chamber, party, tercile], e.g. ["House","R","low"]. Tercile is low, mid or high on DW-NOMINATE first dimension within that chamber and party, or unknown where no score or too few members exist to cut terciles. |
strongest | object | null | {industry, index} for the member’s highest positive index, or null if they are measured and no industry clears the conjunction (the measured, none found state). |
industries | object | Map of industry id → pair record, for every industry where this member cleared all four floors. |
members[bioguide].industries[industry]
| Field | Type | Meaning |
|---|---|---|
index | number, 3 dp | The Donor Alignment Index: sqrt(money_z × vote_z) where both are positive, otherwise exactly 0.0. Not bounded above; in standard-deviation units. |
money_z | number, 3 dp | Money residual: money_share as standard deviations from the peer-group mean for this industry (sample SD). 0.0 if every peer is identical. |
vote_z | number, 3 dp | Vote residual: vote_rate as standard deviations from the same peer group’s mean. |
money_share | number, 5 dp | This industry’s direct PAC contributions as a share (0–1) of all industry-attributed money the member received. |
money_dollars | integer | Those contributions in US dollars. Leadership-PAC, joint-fundraising and independent-expenditure money is excluded. |
vote_rate | number, 4 dp | Informativeness-weighted share (0–1) of the industry’s directed roll calls on which the member voted the industry-favoured way. |
vote_coverage | number | Sum of the informativeness weights behind vote_rate. Higher means the rate rests on more contested votes. |
votes | integer | Number of directed roll calls behind vote_rate. |
peers | integer | Size of the peer population the residuals were taken against: members of the same peer group who also cleared the floors in this industry. |
alignment.csv — columns
The CSV is a derived convenience copy. When it and the JSON disagree, the JSON is authoritative.
Rows are in a fixed order: measured pairs first, by bioguide then industry_id;
then one row per not-measured official. Numbers are written exactly as they appear in the JSON.
Empty cells mean no value, never zero. Booleans are true/false.
There are two kinds of row. A pair row exists for every member × industry pair in
alignment.json, so the number of rows whose pair_state is not
not_measured equals the number of pairs in the JSON. A not-measured row
exists, once, for each official in the roster with no record in the JSON; its industry and figure
columns are empty. A pair that is simply missing for a member who is measured elsewhere fell below a
floor in that industry and has no row.
| Column | Source | Meaning |
|---|---|---|
bioguide | JSON key | Congressional Bioguide id. Empty for the President, Vice President and Justices, who have none. |
site_id | roster id | The site’s own slug for the official; unique, and filled for every row. |
name | roster | Display name. |
chamber | roster role | House, Senate, POTUS, VP or SCOTUS. |
state | roster | Two-letter postal code; N/A where not state-based. |
party | roster | D, R, I, or N/A. |
member_state | derived | The official’s state as shown on the site: measured_alignment (strongest is not null), measured_none (measured, no positive index anywhere) or not_measured. |
industry_id | JSON key | Industry id, e.g. oil_gas. |
industry_label | industries | Human-readable industry name. |
industry_sector | industries | Broad sector, e.g. energy, finance. |
pair_state | derived | measured_alignment where index > 0; measured_none where the pair cleared every floor but index is 0; not_measured on not-measured rows. |
is_strongest | derived | true on the single pair named in the member’s strongest; otherwise false. Empty on not-measured rows. |
index … peers | pair record | index, money_z, vote_z, money_share, money_dollars, vote_rate, vote_coverage, votes, peers — exactly as defined in the JSON schema above. |
peer_group_key | peer_group | The three parts joined with |, e.g. House|R|low. Use it to group rows into the populations the residuals were computed against (together with industry_id). |
peer_chamber, peer_party, peer_tercile | peer_group | The same three parts as separate columns. |
Spreadsheet users: open the file through an import dialog and declare it UTF-8, or accented names may
display incorrectly. Treat bioguide as text.
Reading it responsibly
- The index is relative to a peer group, not to Congress. Indices in different peer groups or industries are not on a common absolute scale.
- Always read
indexbesidemoney_dollars,votesandpeers. A small denominator can produce a large residual. - A
measured_nonerow is a finding: the member is measured in that industry and is not above their peers on both measures. A missing row is not a finding. - There is deliberately no overall per-person score. Do not sum or average indices across industries to make one.
Upstream feeds
The scorer reads four intermediate feeds published by congressvotetracker, each built from public records. They are published so the inputs can be checked independently of this output.
| Feed | Contents | Built from |
|---|---|---|
money_industry.json | Direct PAC contributions per member per industry; the industry taxonomy | FEC bulk downloads (committee master, contributions to candidates) |
vote_positions.json | Per roll call, the vote each industry wanted, composed with motion polarity | govinfo BILLSTATUS subjects and amendments; machine-assigned direction calls with published reasoning |
vote_unity.json | Per roll call, the informativeness weight (largest share of any party that broke ranks) | Voteview |
member_votes.json | Member positions, peer keys and DW-NOMINATE first dimension | Voteview |
The roster (politicians.json) is drawn from
@unitedstates/congress-legislators (CC0).
Update cadence
A scheduled job runs every day at 12:00 UTC, after the upstream morning refresh. It
recomputes the index from the live feeds, runs the independent verification in
pipeline/verify_score.py, and publishes only if every check passes: a wrong index is
worse than a stale one. It commits only when the data has actually changed —
a run that differs in nothing but updated_utc commits nothing. So the file’s
updated_utc records the last change of substance, and the repository history is a
complete, dated record of every version. If an upstream feed is unreachable the previous file is left
untouched.
The CSV is regenerated from the JSON by python3 pipeline/export.py and always
corresponds to the alignment.json in the same commit. For a fixed snapshot, cite the
commit or record updated_utc.
Licence
The code, and the derived data files in this repository, are released under the MIT licence © 2026 AXIA Enterprises: use, copy, modify and redistribute freely, keeping the copyright and permission notice. The underlying records are US government public records (FEC, Congress) and Voteview data; the roster is CC0. Reuse should keep the non-allegation notice below with any figure attributed to a named person.
How to cite
AXIA Enterprises. Donor Alignment Index, 119th Congress [data set]. The Corruption Detector. https://corruptiondetector.org/data.html File: data/alignment.json, updated_utc <value from the file>. Accessed <date>.
In prose: “According to the Donor Alignment Index published at corruptiondetector.org, [member] is [index] standard deviations above comparable legislators on both [industry] PAC money and [industry]-favoured votes ([dollars], [votes] roll calls, peer group of [peers]). The index is a statistical association, not an allegation of wrongdoing.” Please give the dollars and roll-call count alongside any index you quote.
What the data does not mean
It is a statistical association between contributions received and votes cast, relative to comparable legislators. It is not a finding of corruption, bribery, or any other crime, and no allegation of wrongdoing is made about any person named in these files. Accepting lawful contributions from an industry whose position you already hold is ordinary politics. Causation cannot be read off this data in either direction. A high index is a reason to look more closely at a relationship, and nothing more than that. The PAC-MONEY™ game is satire and contributes nothing to these files.
← Back to the index · Methodology · Notes for AI assistants · The satire game