curl --request GET \
--url https://api.financialdatasets.ai/politician-trades \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/politician-trades"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.financialdatasets.ai/politician-trades', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.financialdatasets.ai/politician-trades",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.financialdatasets.ai/politician-trades"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.financialdatasets.ai/politician-trades")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/politician-trades")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"politician_trades": [
{
"name": "<string>",
"chamber": "house",
"state": "<string>",
"district": "<string>",
"owner": "self",
"ticker": "<string>",
"asset_name": "<string>",
"asset_type": "<string>",
"transaction_type": "purchase",
"sale_type": "full",
"transaction_date": "2023-12-25",
"notification_date": "2023-12-25",
"filing_date": "2023-12-25",
"amount_low": 123,
"amount_high": 123,
"filing_status": "new",
"description": "<string>",
"comment": "<string>",
"report_url": "<string>"
}
],
"next_page_url": "<string>"
}{
"error": "Bad Request",
"message": "Invalid request parameters"
}{
"error": "Unauthorized",
"message": "Invalid API key provided"
}{
"error": "Payment Required",
"message": "This endpoint requires a paid subscription. Please upgrade your plan."
}{
"error": "Not Found",
"message": "Ticker XXXX not found"
}Congressional Trading API (House Stock Trades)
Stock trades disclosed by members of the US House of Representatives: 57,000+ trades since 2014, updated within minutes after each report goes public.
curl --request GET \
--url https://api.financialdatasets.ai/politician-trades \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/politician-trades"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.financialdatasets.ai/politician-trades', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.financialdatasets.ai/politician-trades",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.financialdatasets.ai/politician-trades"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.financialdatasets.ai/politician-trades")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/politician-trades")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"politician_trades": [
{
"name": "<string>",
"chamber": "house",
"state": "<string>",
"district": "<string>",
"owner": "self",
"ticker": "<string>",
"asset_name": "<string>",
"asset_type": "<string>",
"transaction_type": "purchase",
"sale_type": "full",
"transaction_date": "2023-12-25",
"notification_date": "2023-12-25",
"filing_date": "2023-12-25",
"amount_low": 123,
"amount_high": 123,
"filing_status": "new",
"description": "<string>",
"comment": "<string>",
"report_url": "<string>"
}
],
"next_page_url": "<string>"
}{
"error": "Bad Request",
"message": "Invalid request parameters"
}{
"error": "Unauthorized",
"message": "Invalid API key provided"
}{
"error": "Payment Required",
"message": "This endpoint requires a paid subscription. Please upgrade your plan."
}{
"error": "Not Found",
"message": "Ticker XXXX not found"
}Overview
The Financial Datasets politician trades API returns the stock trades that members of the US House of Representatives disclose. It tells you which stocks members of the House bought or sold, within minutes after each report goes public. Every trade is read directly from the official disclosure reports, which come from authoritative government sources (data provenance). You can call it as a REST endpoint with an API key, or from Claude, ChatGPT, Cursor, and other AI apps through the MCP server, or pay per request with x402. Pricing starts at $20. With no filter, the endpoint is a feed of the newest disclosures from every member. Add filters to answer questions like:- Which members of the House sold Nvidia this year?
- What did members from Texas buy last month?
- Which trades over $1,000,000 did a member’s spouse make?
Coverage
| Chamber | Members | Trades | Years of Coverage | Updated |
|---|---|---|---|---|
| House | 320+ | 57,000+ | 2014 onward | Within minutes after each report goes public |
transaction_date is often weeks before its filing_date. Use filing_date to see what became public, and transaction_date to see when the trade happened.
Available Members
You can fetch the list of members with a trade on record, with their chamber and state, with aGET request to:
https://api.financialdatasets.ai/politician-trades/names/
Getting Started
There are only 3 steps for making a successful API call:- Add your API key to the header of the request as
X-API-KEY. - Add query params like
tickerandlimitto filter the data. - Execute the API request.
The Response
Each trade is one row of a member’s report. Most fields are as filed. These need a word:amount_lowandamount_high: members report a dollar range, not an exact amount. A trade of “$1,001 - $15,000” hasamount_low1001 andamount_high15000. When a member reports an exact amount,amount_lowandamount_highare equal.owner: whose account made the trade:self,spouse,joint, ordependent_child.transaction_type:purchase,sale, orexchange.sale_type:partialwhen the report marks a sale as partial,fullwhen it marks it as full, andnullwhen the report does not say.filing_status:newfor a first report of the trade,amendedfor a corrected row, anddeletedfor a row the member withdrew.ticker: the ticker as the member reported it, ornullwhen the member did not report one.report_url: the official report the trade comes from.
Filtering the Data
No parameter is required. With no filter, you get the newest disclosures first. You can filter the data byticker, name, chamber, transaction_type, state, owner, amount_gte, filing_date, and transaction_date, and sort with order_by. All filters combine.
Note: by default, limit is 10 and order_by is filing_date.
The ticker parameter is used to filter trades in one stock (e.g., NVDA). Share classes match in both forms: BRK.B and BRK-B give the same trades.
The name parameter is used to filter trades by a member. Every word you send must be in the name, in any case, so a last name alone is enough. You can get the list of names from the /names endpoint above.
The chamber parameter is house or senate.
The transaction_type parameter is purchase, sale, or exchange.
The state parameter is the member’s two-letter state code (e.g., TX), in any case.
The owner parameter is self, spouse, joint, or dependent_child.
The amount_gte parameter keeps trades whose amount_low is at least this many whole dollars. For example, amount_gte=1000001 keeps the “$1,000,001 - $5,000,000” range and up.
The filing_date and transaction_date parameters filter by date in YYYY-MM-DD format. For example, transaction_date_gte=2025-01-01 and transaction_date_lte=2025-12-31 give the trades made in 2025.
The available date operations are:
filing_date,filing_date_gte,filing_date_lte,filing_date_gt,filing_date_lttransaction_date,transaction_date_gte,transaction_date_lte,transaction_date_gt,transaction_date_lt
order_by parameter sets the order:
filing_date(default): newest disclosure first.transaction_date: newest trade first.
limit parameter is the total number of trades to return across all pages. Each page holds up to 10 trades, linked by next_page_url. The maximum value is 5000.
Example (the feed)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# the newest disclosures from every member
url = 'https://api.financialdatasets.ai/politician-trades?limit=10'
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
Example (with ticker)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'NVDA' # stock ticker
limit = 100 # number of trades to return
# create the URL
url = (
f'https://api.financialdatasets.ai/politician-trades'
f'?ticker={ticker}'
f'&limit={limit}'
)
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
Example (with name)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
name = 'last_name' # every word must be in the member's name; see /politician-trades/names
# create the URL
url = (
f'https://api.financialdatasets.ai/politician-trades'
f'?name={name}'
f'&limit=100'
)
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
Example (with state and transaction_date)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
state = 'TX' # member's state
transaction_date_gte = '2025-01-01' # trades made on or after this day
# create the URL
url = (
f'https://api.financialdatasets.ai/politician-trades'
f'?state={state}'
f'&transaction_date_gte={transaction_date_gte}'
f'&limit=100'
)
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
Example (with owner and amount_gte)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
owner = 'spouse' # whose account made the trade
amount_gte = 1000001 # the trade's low bound is at least $1,000,001
# create the URL
url = (
f'https://api.financialdatasets.ai/politician-trades'
f'?owner={owner}'
f'&amount_gte={amount_gte}'
f'&limit=100'
)
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
Example (newest trades first)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# sort by the day of the trade, not the day it was disclosed
url = (
f'https://api.financialdatasets.ai/politician-trades'
f'?order_by=transaction_date'
f'&limit=100'
)
# make API request
response = requests.get(url, headers=headers)
# parse politician_trades from the response
politician_trades = response.json().get('politician_trades')
FAQ
Where does the politician trading data come from?
From authoritative government sources: the official trade reports that members of the House file. Each report is read into one structured record per trade.How fast do new trades show up?
Within minutes after each report goes public.Why is the trade date weeks before the filing date?
A member has up to 45 days to report a trade. The trade happened ontransaction_date; it became public on filing_date.
Why is the amount a range?
Members report a dollar range, not an exact amount. We serve the range as filed inamount_low and amount_high, and never guess a figure inside it.
Do you cover the Senate?
Not yet. Senate trades are coming soon.Can an AI agent use this data?
Yes. Claude, ChatGPT, Cursor, and other MCP clients reach it through the Financial Datasets MCP server. An agent with a wallet can also pay per request with x402, with no account.Authorizations
API key for authentication.
Query Parameters
Filter by stock ticker (e.g., 'NVDA'). Share classes match in both forms: 'BRK.B' and 'BRK-B' give the same trades.
Filter by member name. Every word must be in the name, in any case, so a last name alone is enough. Use the /politician-trades/names endpoint to get the names.
Filter by chamber of Congress.
house, senate Filter by type of trade.
purchase, sale, exchange Filter by the member's two-letter state code (e.g., 'TX'), in any case.
2Filter by whose account made the trade.
self, spouse, joint, dependent_child Keep trades whose amount_low is at least this many whole dollars (e.g., 1000001 keeps the $1,000,001 - $5,000,000 range and up).
x >= 0Filter by the date the report was filed: equal to this date (YYYY-MM-DD).
Filter by the date the report was filed: on or after this date (YYYY-MM-DD).
Filter by the date the report was filed: on or before this date (YYYY-MM-DD).
Filter by the date the report was filed: after this date (YYYY-MM-DD).
Filter by the date the report was filed: before this date (YYYY-MM-DD).
Filter by the date of the trade: equal to this date (YYYY-MM-DD).
Filter by the date of the trade: on or after this date (YYYY-MM-DD).
Filter by the date of the trade: on or before this date (YYYY-MM-DD).
Filter by the date of the trade: after this date (YYYY-MM-DD).
Filter by the date of the trade: before this date (YYYY-MM-DD).
The order of the trades: filing_date (default) puts the newest disclosure first; transaction_date puts the newest trade first.
filing_date, transaction_date The maximum number of trades to return (default: 10, max: 5000). This is the total across all pages, not a page size: each page holds up to 10 records, linked by next_page_url.
Opaque pagination cursor from a previous response's next_page_url. When provided, all other query parameters are ignored: the cursor carries the original request's filters. Treat it as opaque; do not construct or modify it.