The suspicion is old and simple: that the companies which give to campaigns and pay lobbyists are the same ones that win federal contracts. The data to examine it is entirely public — campaign-finance filings, lobbying disclosures, and the federal spending ledger — but it sits in three systems that share no common key. This is how to join them, and, just as important, what the join can and cannot prove.
The three datasets
- FEC campaign finance — the giving: corporate and trade-association PACs, their contributions, and (via super PACs) independent expenditures.
- Lobbying disclosures — the asking: registrants, their clients, the issues and bills lobbied, and the dollars reported under the Lobbying Disclosure Act.
- USAspending — the receiving: federal contract awards to companies, by agency, with amounts and (via subawards) the money that flows downstream.
The hard part: there is no shared key
Unlike the cleaner pipelines — a drug has an NDC, a nonprofit has an EIN — the influence pipeline has no common identifier. The FEC keys on committee IDs, the lobbying registry on its own client and registrant numbers, and USAspending on UEI/DUNS. The only thing that runs across all three is the organization name, which means the entire join rests on entity resolution to a parent company. Subsidiaries give, lobby, and contract under different legal names; resolve them to the parent first, or the same company looks like three unrelated ones. This is the single hardest and most consequential step.
# There is NO shared identifier across these three datasets. FEC uses committee
# IDs, the lobbying registry uses its own client/registrant IDs, and USAspending
# uses UEI/DUNS. The only bridge is the organization name (and its parent).
import requests
# 1. FEC: PAC contributions and spending tied to a sponsor organization.
fec = requests.get("https://api.open.fec.gov/v1/committees/",
params={"q": "Lockheed Martin", "api_key": "DEMO_KEY"}, timeout=30)
# 2. Lobbying disclosures: registrants, clients, issues, and reported spend.
# (Senate LDA / House Clerk filings — bulk XML.)
# 3. USAspending: federal contract awards to the same parent company.
usa = requests.post("https://api.usaspending.gov/api/v2/search/spending_by_award/",
json={"filters": {"recipient_search_text": ["Lockheed Martin"],
"award_type_codes": ["A", "B", "C", "D"]}, # contracts
"fields": ["Recipient Name", "Award Amount", "Awarding Agency"]}, timeout=30)
# Resolve to a parent entity first (subsidiaries file separately in all three),
# then compare the three flows for the SAME parent over aligned periods.What it can show — and what it can't
Joined carefully, the pipeline supports real, bounded findings: which contractors are also the largest PAC givers and lobbying spenders; whether a company's lobbying on a specific appropriations bill precedes contract awards from the relevant agency; and how the three flows move together over time for one parent. What it cannotdo is prove that the giving bought the contract. These are correlations across public filings, confounded by the plain fact that big government contractors are big companies that do all three things at scale. The honest output is a measured association with its caveats attached — the same discipline the rest of this work insists on.
The gotchas
- Parent resolution. Subsidiaries and affiliated PACs file separately; without a parent crosswalk the flows fragment.
- Reporting periods differ. FEC is on election cycles, lobbying on quarters, contracts on the federal fiscal year — align on dates, not labels.
- Lobbying spend is bundled. LDA reports a single dollar figure across all issues for a client, not per-issue or per-contract.
- Direction and intent are invisible. The data shows that money moved, not why — never render correlation as a quid pro quo.
Related writing: Following the Money — the broader synthesis on tracing an entity across federal spending and ownership, of which this influence join is one (name-keyed) case.
See also: Lobbying disclosure data — the dataset behind the lobbying stage, and the entity-resolution problem it shares with the rest of the pipeline.