Congressional Trading API
Retrieve stock trading activity from US House Representatives and Senators disclosed under the STOCK Act. House and Senate trades are served by separate endpoints with an identical schema.
Endpoints
Section titled “Endpoints”GET /v2/congress/house/{symbol}GET /v2/congress/senate/{symbol}Authentication
Section titled “Authentication”The API supports multiple authentication methods:
| Method | Example |
|---|---|
| Bearer token (recommended) | Authorization: Bearer YOUR_API_KEY |
| X-API-Key header | X-API-Key: YOUR_API_KEY |
| Query parameter | ?apiKey=YOUR_API_KEY |
| Legacy query parameter | ?token=YOUR_API_KEY |
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
symbol |
string | Yes | Stock ticker symbol (e.g., AAPL, NVDA) |
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
startDate |
string | No | Start date (YYYY-MM-DD) |
endDate |
string | No | End date (YYYY-MM-DD) |
limit |
integer | No | Maximum number of results to return |
Request
Section titled “Request”from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
house_df = fb.house_trades.ticker("NVDA", date_from="2025-01-01", date_to="2025-06-30", as_dataframe=True)senate_df = fb.senate_trades.ticker("NVDA", date_from="2025-01-01", date_to="2025-06-30", as_dataframe=True)print(house_df)print(senate_df)curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/congress/house/AAPL"
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.finbrain.tech/v2/congress/senate/AAPL"import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
for chamber in ["house", "senate"]: response = requests.get( f"https://api.finbrain.tech/v2/congress/{chamber}/AAPL", headers=headers, params={"limit": 10} ) data = response.json()
for t in data["data"]["trades"]: print(f"{t['date']} - {t['politician']} ({chamber}): " f"{t['transactionType']} ({t['amount']})")#include <iostream>#include <string>#include <curl/curl.h>#include <nlohmann/json.hpp>
using json = nlohmann::json;
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) { userp->append((char*)contents, size * nmemb); return size * nmemb;}
json get_congress_trades(const std::string& chamber, const std::string& symbol, const std::string& api_key) { CURL* curl = curl_easy_init(); std::string response;
if (curl) { std::string url = "https://api.finbrain.tech/v2/congress/" + chamber + "/" + symbol;
struct curl_slist* headers = nullptr; std::string auth_header = "Authorization: Bearer " + api_key; headers = curl_slist_append(headers, auth_header.c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_perform(curl); curl_slist_free_all(headers); curl_easy_cleanup(curl); }
return json::parse(response);}
int main() { for (const std::string& chamber : {"house", "senate"}) { auto result = get_congress_trades(chamber, "AAPL", "YOUR_API_KEY");
for (auto& t : result["data"]["trades"]) { std::cout << t["date"].get<std::string>() << " - " << t["politician"].get<std::string>() << " (" << chamber << "): " << t["transactionType"].get<std::string>() << " (" << t["amount"].get<std::string>() << ")" << std::endl; } }
return 0;}use reqwest::blocking::Client;use serde::Deserialize;use std::error::Error;
#[derive(Debug, Deserialize)]struct CongressTrade { date: String, politician: String, #[serde(rename = "transactionType")] transaction_type: String, amount: String,}
#[derive(Debug, Deserialize)]struct CongressData { symbol: String, name: String, chamber: String, trades: Vec<CongressTrade>,}
#[derive(Debug, Deserialize)]struct CongressTradesResponse { success: bool, data: CongressData,}
fn get_congress_trades(chamber: &str, symbol: &str, api_key: &str) -> Result<CongressTradesResponse, Box<dyn Error>> { let url = format!( "https://api.finbrain.tech/v2/congress/{}/{}", chamber, symbol );
let client = Client::new(); let response: CongressTradesResponse = client .get(&url) .bearer_auth(api_key) .send()? .json()?;
Ok(response)}
fn main() -> Result<(), Box<dyn Error>> { for chamber in ["house", "senate"] { let result = get_congress_trades(chamber, "AAPL", "YOUR_API_KEY")?;
for t in &result.data.trades { println!("{} - {} ({}): {} ({})", t.date, t.politician, chamber, t.transaction_type, t.amount); } }
Ok(())}for (const chamber of ["house", "senate"]) { const response = await fetch( `https://api.finbrain.tech/v2/congress/${chamber}/AAPL`, { headers: { "Authorization": "Bearer YOUR_API_KEY" } } ); const result = await response.json();
for (const t of result.data.trades) { console.log(`${t.date} - ${t.politician} (${chamber}): ${t.transactionType} (${t.amount})`); }}Response
Section titled “Response”Success Response (200 OK)
Section titled “Success Response (200 OK)”{ "success": true, "data": { "symbol": "AAPL", "name": "Apple Inc.", "chamber": "house", "trades": [ { "date": "2025-11-24", "politician": "Debbie Dingell", "transactionType": "Sale", "amount": "$50,001 - $100,000" } ] }, "meta": { "timestamp": "2026-01-19T15:06:31.764Z" }}The Senate endpoint returns the same structure with "chamber": "senate".
Response Fields
Section titled “Response Fields”| Field | Type | Description |
|---|---|---|
success |
boolean | Whether the request was successful |
data.symbol |
string | Stock ticker symbol |
data.name |
string | Company name |
data.chamber |
string | Congressional chamber (house or senate) |
data.trades |
array | Array of trade objects |
meta.timestamp |
string | Response timestamp (ISO 8601) |
Trade Object Fields
Section titled “Trade Object Fields”| Field | Type | Description |
|---|---|---|
date |
string | Transaction date (YYYY-MM-DD) |
politician |
string | Name of the House or Senate member |
transactionType |
string | Transaction type (Purchase or Sale) |
amount |
string | Transaction amount (exact value or range) |
Amount Ranges
Section titled “Amount Ranges”| Range | Min | Max |
|---|---|---|
| $1,001 - $15,000 | $1,001 | $15,000 |
| $15,001 - $50,000 | $15,001 | $50,000 |
| $50,001 - $100,000 | $50,001 | $100,000 |
| $100,001 - $250,000 | $100,001 | $250,000 |
| $250,001 - $500,000 | $250,001 | $500,000 |
| $500,001 - $1,000,000 | $500,001 | $1,000,000 |
| $1,000,001 - $5,000,000 | $1,000,001 | $5,000,000 |
| Over $5,000,000 | $5,000,001 | N/A |
Errors
Section titled “Errors”| Code | Error | Description |
|---|---|---|
| 400 | Bad Request | Invalid symbol |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Authenticated, but not authorized to access this resource |
| 404 | Not Found | Ticker not found |
| 429 | Too Many Requests | Rate limit exceeded — wait and retry |
| 500 | Internal Server Error | Server-side error |
Related
Section titled “Related”- Congressional Trading Dataset - Use cases and analysis examples
- Screener API - Screen congressional trades across tickers
- Insider Transactions - SEC Form 4 data
- Price Forecasts - Price forecasts
