**Use the CongressInvests API to watch specific tickers and fire a Slack alert the moment a new congressional trade is disclosed — no scraping required.
**canonical_url: https://congressinvests.com/blog
Most retail investors find out about congressional stock trades days or weeks after the fact — scrolling through Twitter, or stumbling on a news article. By then, the market has already reacted.
There's a better way. The STOCK Act requires members of Congress to disclose trades within 45 days. Those disclosures are public the moment they're filed. With the CongressInvests API, you can get notified within hours of a new filing — often before most financial media covers it.
In this guide, we'll build a Python bot that watches specific tickers and fires a Slack alert the moment a new congressional trade is disclosed.
What you'll need
Python 3.8+
A Slack webhook URL (free — instructions below)
A CongressInvests API key for real-time webhooks, or just use the free tier (100 req/day) for polling
No API key required for the polling approach in steps 1–3. You'll only need a Pro key for the real-time webhook setup in step 4.
Step 1: Your first API call
No setup needed. Run this from your terminal and you'll get back every NVDA trade filed by Congress in the last year:
curl https://congressinvests.com/trades/NVDA
The response tells you the member's name, chamber, trade type, disclosed dollar range, and — importantly — the last_updated timestamp so you know exactly how fresh the data is:
{
"ticker": "NVDA",
"total": 15,
"last_updated": "2026-05-31T10:04:17Z",
"data_lag_minutes": 14,
"trades": [
{
"member": "John Boozman",
"chamber": "Senate",
"ticker": "NVDA",
"trade_type": "buy",
"amount": "$1,001 - $15,000",
"tx_date": "2026-03-19",
"disclosed": "2026-04-14",
"link": "https://efdsearch.senate.gov/..."
}
]
}
Step 2: Write the polling watcher
Install requests if you haven't:
pip install requests
This script polls a list of tickers every hour, tracks which trades it's already seen, and prints an alert for anything new. It stays well within the free tier's 100 req/day limit even across four tickers.
# watcher.py
import requests
import time
BASE = "https://congressinvests.com"
TICKERS = ["NVDA", "AAPL", "MSFT", "TSLA"]
seen = set()
def check():
for ticker in TICKERS:
resp = requests.get(f"{BASE}/trades/{ticker}", timeout=10)
if not resp.ok:
continue
for t in resp.json().get("trades", []):
key = f"{t['member']}:{t['ticker']}:{t['tx_date']}"
if key not in seen:
seen.add(key)
alert(t)
def alert(t):
action = "BOUGHT" if t["trade_type"] == "buy" else "SOLD"
print(f"🔔 {t['member']} ({t['chamber']}) {action} {t['ticker']} — {t['amount']}")
print(f" Filed: {t['disclosed']} | {t['link']}\n")
while True:
check()
print("Checked. Sleeping 1 hour…")
time.sleep(3600)
Step 3: Add Slack notifications
First, create an Incoming Webhook in your Slack workspace. It takes about two minutes and gives you a URL like https://hooks.slack.com/services/T.../B.../....
Replace the alert() function with one that posts a formatted Slack message:
SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
def alert(t):
action = "🟢 BOUGHT" if t["trade_type"] == "buy" else "🔴 SOLD"
text = (
f"*{action}* — {t['member']} ({t['chamber']})\n"
f"*{t['ticker']}* · {t['amount']} · Filed {t['disclosed']}\n"
f"<{t['link']}|View filing ↗>"
)
requests.post(SLACK_WEBHOOK, json={"text": text}, timeout=5)
Now when Nancy Pelosi files an NVDA trade, you'll get a Slack message within an hour of your next poll cycle.
Tip: Run this on a free-tier cloud VM (Railway, Render, or Fly.io) so it keeps running 24/7 without your laptop staying on.
Step 4: Go real-time with webhooks (Pro)
Polling every hour is fine, but the filing you care about most might land right after a poll. With a Pro API key, you can subscribe to push notifications that fire within minutes of a new filing being detected — no polling loop needed.
Subscribe to a ticker
curl -X POST https://congressinvests.com/webhooks/subscribe \
-H "X-Api-Key: YOUR_PRO_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/hook",
"ticker": "NVDA",
"events": ["any"]
}'
You can also subscribe by politician name instead of ticker — handy if you want to follow a specific member across all their trades:
curl -X POST https://congressinvests.com/webhooks/subscribe \
-H "X-Api-Key: YOUR_PRO_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-server.com/hook", "politician": "Nancy Pelosi"}'
Handle the webhook payload
Your server receives a POST with this payload on every new trade:
{
"event": "new_trade",
"ticker": "NVDA",
"politician": "Nancy Pelosi",
"trade_type": "Purchase",
"amount": "$1,000,001 - $5,000,000",
"filing_date": "2026-05-30",
"transaction_date": "2026-05-15",
"source": "House",
"api_url": "https://congressinvests.com/trades/NVDA"
}
A minimal Flask receiver that pipes it straight to Slack:
# receiver.py
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
@app.route("/hook", methods=["POST"])
def hook():
t = request.get_json()
action = "🟢 BOUGHT" if t["trade_type"] == "Purchase" else "🔴 SOLD"
text = (
f"*{action}* — {t['politician']}\n"
f"*{t['ticker']}* · {t['amount']} · Filed {t['filing_date']}\n"
f"<{t['api_url']}|View all {t['ticker']} trades ↗>"
)
requests.post(SLACK_WEBHOOK, json={"text": text}, timeout=5)
return jsonify({"ok": True})
if __name__ == "__main__":
app.run(port=5000)
Testing locally? Use ngrok to expose your local server:
ngrok http 5000. Then subscribe using the ngrok HTTPS URL as yourwebhook_url.What's next
Multiple tickers: Call/webhooks/subscribeonce per ticker, or subscribe by politician to catch all their trades.
Email instead of Slack: Swap the Slack call forsmtplibor a SendGrid API call.
Store and backtest: Write each trade to SQLite, then backtest: "What if I bought the day a senator disclosed a purchase?"Build a dashboard: Poll
/trades/recentand render a live feed in your own UI using the Python or Node.js SDK.Ready to go real-time? Pro tier unlocks webhook alerts, 50,000 requests/day, and priority cache refresh — starting at $29/month. Get Pro access →
Data sourced from Senate EFD and the House Clerk's Office. For informational and research purposes only — not financial advice.
Top comments (0)