How we source this / Method
Method
The exact recipe behind every dollar figure, written for anyone who wants to check it.
How every number is made
Plain-language version on the site at /sources/. This file is the exact recipe. Everything here is public data.
The two committees
| Committee | FEC ID | What it is | First filed |
|---|---|---|---|
| American Israel Public Affairs Committee Political Action Committee ("AIPAC PAC") | C00797670 | AIPAC's PAC. Gives directly to candidates, and acts as a conduit for contributions individuals earmark for candidates. FEC type: PAC, qualified; lobbyist/registrant PAC. | 2021-12-15 |
| United Democracy Project ("UDP") | C00799031 | AIPAC's super PAC. Spends independently for or against candidates (independent expenditures). FEC type: Super PAC (independent expenditure-only). | 2022-01-03 |
Both IDs were looked up through the FEC's committee search (/v1/committees/?q=…) on 2026-10-18. The names on the
site are the names in the filings. The money is American by law (foreign nationals may not contribute or spend in
US elections), so the site never calls it "Israeli" (U-6, U-D4).
Where the rows come from
- The filing list.
GET https://api.open.fec.gov/v1/committee/<ID>/filings/?per_page=100&sort=-receipt_date(paged), for both committees. Kept: every filing the FEC marksmost_recent(so an amended report replaces its original) with form type F3X (periodic report) for AIPAC PAC, and F3X plus F24 (24- and 48-hour independent-expenditure notices) for UDP. - The filings themselves. Each kept filing is read in full from its electronic original,
https://docquery.fec.gov/dcdev/posted/<file number>.fec, the exact file the committee submitted. No API key is needed for these, and they never change once filed, so each is downloaded once. - The rows (
pipeline/fec_money.py, parsed with thefecfilelibrary):
| Figure | Rows | Rule |
|---|---|---|
| AIPAC PAC direct | AIPAC PAC Schedule B, line 23 (contributions to federal candidates and committees) | Rows that are not earmarks (below). Minus Schedule A line 16 rows (refunds the candidate's committee sent back to AIPAC PAC). Who each row counts for: see "Who a row counts for". |
| AIPAC PAC earmarked | AIPAC PAC Schedule B, line 23 | Rows whose purpose or memo text matches earmark|(?<![a-z])ermk (case ignored): "Earmark of |
| AIPAC PAC, to a joint fundraising committee | AIPAC PAC Schedule B, line 23 | Rows paid to a committee the FEC designates J (joint fundraising), which splits its money among several committees. Not counted as money to the candidate; shown on its own line beside the candidate the row names (Jeffries Victory Fund) or, where the row names none, the candidate the committee is for (Susan Collins for Maine, set by hand in JFC_OWNER). |
| UDP supporting | UDP Schedule E (independent expenditures) | Support/oppose indicator S. Attributed to the candidate ID on the row. |
| UDP opposing | UDP Schedule E | Support/oppose indicator O. |
- Memo rows (memo code
X) itemise detail of another row and are skipped, so nothing is counted twice. - 24/48-hour notices vs periodic reports. A UDP periodic report (F3X) lists every expenditure in its period, including those already announced in 24/48-hour notices. So notice rows are used only for expenditures dated after the end of UDP's latest periodic report, and each transaction once.
- Blank candidate IDs. 96 UDP rows from 2022 name the candidate but leave the ID blank. They are matched to the
FEC candidate master files (
cn22,cn24,cn26) by office, state, district and name, and used only when exactly one candidate fits (all 96 matched; the rows carryby_name: true). - Dates and cycles. A row's date is the expenditure date (UDP: dissemination date where given). The 2026 cycle is 2025-01-01 to 2026-12-31. Career is everything since each committee began filing (AIPAC PAC December 2021, UDP January 2022), so no figure implies giving before AIPAC PAC existed.
Who a row counts for (pipeline/totals.py, fact check W1-W8, M2)
- UDP rows: the candidate the expenditure names.
- AIPAC PAC rows: the candidate ID AIPAC PAC typed on the row, if the FEC's candidate-committee linkage files
(
ccl22/24/26) tie that ID to the committee the money was paid to, or the committee has no links. If the ID isn't tied to the recipient committee, the row counts for the candidate(s) that committee is a principal or authorized committee (designation P or A) for. Example: 307 rows paid to Pete Ricketts for Senate (C00832436) carry ID S4NE00173, which is in no FEC candidate file; the linkage file ties the committee to S6NE00129, his ID. - Joint fundraising committees (designation J in the committee master
cm22/24/26): their own figure, above. - A row counted for two of one person's IDs counts once.
Which cycle a row counts in (pipeline/fec_money.py, fact check M1)
- Its own date, except a negative row (a refund, or a VOID cancelling an earlier check), which counts in the cycle of what it reverses: a date written in its description ("Refund of contribution made 02/15/2022"); else a year written in it ("Refund of General 2024 Contribution"); else the latest earlier gift of the same kind and amount to the same committee (AIPAC PAC) or about the same candidate (UDP); else the latest earlier gift of that kind there; else its own date. A refund in 2026 of a 2022 gift no longer pulls a 2026 figure below zero.
- No figure is ever shown negative. Where refunds bring a figure to $0, it reads "$0 (net of $X refunded)".
After this rule, no figure in the data is negative;
tools/test_money_fixes.pyfails if one ever is.
From rows to a person (pipeline/people.py, pipeline/totals.py)
Each person's figure is the sum over every FEC candidate ID they have filed under, House and Senate:
- sitting senators: the FEC IDs in the congress-legislators dataset (public domain, unitedstates.github.io);
- 2026 candidates: those IDs, plus the FEC candidate master files matched by state, office and name; five people
file under another form of their name and were matched by hand (Hinson as "Arenholz", Rogers as "Michael J",
Tache as "Joseph", Flanagan as "Margaret", Fetty Anderson as "Rachel Lee"; see FEC_EXTRA in people.py).
The House (pipeline/house.py)
-
Merging FEC IDs (fact check K1): two or more FEC IDs found by name are merged into one person only when each was filed for the same district as the 2026 race; anything else needs a hand check (
FEC_HOUSE). This unmerged three different Florida Davises and two California Smiths. A single matching ID is kept. IDs a person's own records leave out are added by hand inFEC_ADD(Tom Kean Jr.'s 2006 Senate ID, S6NJ00271). -
Who is on the ballot:
data/house/<ST>.yaml, every candidate on each state's certified 2026 general-election ballot for U.S. House (not write-ins). Each name is copied exactly as the source prints it, andtools/verify_house.pyfetches the source and fails unless every name is on it and the state has its full number of districts. Sources are the state election office's list, or the House Clerk's compilation of nominees from official sources (Oct 8, 2026), or an established news report where neither could be read. - Cross-check:
tools/check_house_clerk.pycompares every district with the House Clerk's list. Each difference is explained indocs/house-clerk-check.md. - FEC IDs: a sitting member's own IDs from congress-legislators; otherwise FEC House records in the same state
whose last name matches exactly and whose first name, middle name or listed nickname matches (with common
nicknames: Bob for Robert, Jim for James and so on). One person often has an ID per cycle under slightly
different spellings; all are counted, and any such merged match that carries money is listed for a hand check
(none does). A few are set by hand (
FEC_HOUSEin house.py). A candidate with no FEC record is shown as having none: every 2026-cycle row that names no candidate is money to a party or caucus committee. - Money: the same four figures, from the same rows, recomputed by the same independent check.
- District lines: races are listed by the 2026 districts on the ballot. Several states use new lines in 2026; each state's page says so, with a source. The ZIP lookup for calling uses the current (119th Congress) districts, because a caller reaches today's member, elected on today's lines (Census ZCTA-to-119th-Congress relationship file; a ZIP crossing districts offers each district's member).
Odds of winning (pipeline/odds.py)
- Source: Kalshi's public, read-only market data (api.elections.kalshi.com), fetched once a day. House:
series
KXHOUSERACE, one market per candidate or party per district. Senate:SENATE<ST>,KXSENATE<ST>andKX<ST>SENATE, plusSENATEOHSandSENATEFLSfor the specials. Only 2026 general-election markets are kept. - Matching: a market's subtitle names the candidate; it is matched to a candidate in the same race by last name and first name or nickname. A market named only "Democratic party" or "Republican party" goes to that party's nominee where the race has exactly one. Senate markets are placed by the state their own title or rules name (Kalshi files Kentucky's under a Louisiana series). Where a person has two markets, the busier one is used.
- The figure: the midpoint of the best yes bid and ask, else the last trade, shown as a percentage (half-up, from the price to 4 places), "under 1%" and "over 99%" at the ends. Nothing is shown without a price.
- Check:
tools/verify_odds.pyrecomputes every figure from the saved raw data (data/odds-raw.json.gz) with separate code, confirms each market names the same person in the same district, and finds the figure on the built pages. The daily job guards the fetch like the others: a failed or shrunken fetch keeps the last good data. - What it is not: a poll, a forecast or our opinion. It's what traders are willing to pay, and it can be wrong.
How current it is
- AIPAC PAC: monthly reports. The latest covers through 2026-08-31 (filed 2026-09-19). The September report is due 2026-10-20; the daily job picks it up.
- UDP: monthly reports through 2026-08-31, plus 24/48-hour notices through 2026-10-16.
- Every money section on the site shows these dates.
Checks
- Recompute (
tools/verify_money.py): rebuilds every published figure (1,384 of them: 4 measures × cycle and career × 173 people) straight from the raw.fecfiles with separate code (plain FEC format field positions, nofecfile), and must match to the cent. Proven able to fail: changing one published total by $1 fails it. - Against FEC's processed data: UDP's 2026 totals per candidate match the FEC bulk independent-expenditure file
(
independent_expenditure_2026.csv) within 0.4%; the gap is notices FEC had not processed yet. FEC's processed "committee contributions" bulk file (pas226) is not a usable yardstick for AIPAC PAC: it codes many of AIPAC PAC's amended earmark rows as direct contributions (transaction type 24K), e.g. 70,724 dollars of "direct" contributions to one House candidate, far over the legal limit for a direct contribution. The filings' own wording ("Earmark of …") is used instead. - Against OpenSecrets (required five-candidate cross-check): not completed in the build session.
opensecrets.org refuses scripts (HTTP 403) and shows a bot check in a browser, which this build does not try to get
past. The five figures to compare, with the OpenSecrets pages to read by hand, are in
docs/opensecrets-check.md. Expected differences, written down before the comparison: OpenSecrets reports AIPAC money as "PAC" plus "individuals" (bundled), groups giving by cycle, may count earmarks from the recipient's side (their Schedule A memo entries naming AIPAC PAC as conduit) rather than AIPAC PAC's own Schedule B, and updates on its own schedule.
Limits, said plainly
- These figures cover AIPAC PAC and UDP only (U-D4). Other pro-Israel PACs and individual donors who don't route through AIPAC PAC are not counted.
- "Direct" money goes to a candidate's committee, which may have been for an earlier House race; each person's rows page shows which committee received each contribution.
- The FEC's own website search (linked beside each figure) shows processed data, which can lag the filings by weeks.