DEV Community

lulzasaur
lulzasaur

Posted on

How I Built an SEC Insider Trading Alert System With 3 API Calls

How I Built an SEC Insider Trading Alert System With 3 API Calls

Every public company insider — CEOs, CFOs, board members — is legally required to report stock trades to the SEC within two business days via Form 4 filings. That's 200+ filings per day, all public data, and it's one of the most reliable trading signals available.

I built an API that polls EDGAR, parses the XML, and returns clean JSON. Here's how to use it to build a real-time insider trading alert system.

Why Insider Trades Matter

Academic research consistently shows that insider purchases outperform the market by 7-10% annually. When a CEO buys $2M of their own stock on the open market, they're putting personal money where their mouth is. That's a signal worth tracking.

The problem: SEC EDGAR returns raw XML/SGML documents designed for regulators, not developers. Parsing Form 4 filings means dealing with accession numbers, CIK lookups, and XML namespaces.

The API handles all of that and returns structured JSON.

Quick Start: Get Recent Insider Trades

The simplest call — fetch the latest insider trades across all companies:

import requests

API_URL = "https://sec-edgar-insider-alerts-production.up.railway.app"

# Get recent insider trades (last 3 days)
response = requests.get(f"{API_URL}/sec/insider-trades", params={
    "days": 3,
    "limit": 20
})

data = response.json()
print(f"Found {data['total']} filings")

for filing in data["filings"]:
    print(f"{filing['filedDate']} | {filing['insider']['name']} | {filing['company']['name']}")
Enter fullscreen mode Exit fullscreen mode

Output:

Found 847 filings
2026-03-27 | Tim Cook | Apple Inc.
2026-03-27 | Jensen Huang | NVIDIA Corp
2026-03-26 | Satya Nadella | Microsoft Corporation
...
Enter fullscreen mode Exit fullscreen mode

Filter by Company Ticker

Want to monitor a specific stock? Use the company endpoint:

# Get all AAPL insider trades in the last 30 days
aapl = requests.get(f"{API_URL}/sec/insider-trades/company/AAPL", params={
    "days": 30,
    "limit": 50
})

data = aapl.json()
print(f"AAPL insider trades: {data['total']}")

for filing in data["filings"]:
    insider = filing["insider"]["name"]
    date = filing["filedDate"]
    print(f"  {date}{insider}")
Enter fullscreen mode Exit fullscreen mode

This covers 10,400+ ticker symbols — basically every public company on EDGAR.

Get Full Transaction Details

The filing detail endpoint is where it gets interesting. Each Form 4 contains the actual transaction data — shares bought/sold, price per share, and post-transaction holdings:

# Get full Form 4 details
detail = requests.get(
    f"{API_URL}/sec/insider-trades/filing/0002114927-26-000005"
)

filing = detail.json()
print(f"Insider: {filing['owner']['name']}")
print(f"Company: {filing['issuer']['name']} ({filing['issuer']['ticker']})")
print(f"Role: Director={filing['owner']['isDirector']}, Officer={filing['owner']['isOfficer']}")

for tx in filing["transactions"]:
    action = tx["codeLabel"]  # "Purchase", "Sale", "Option Exercise"
    shares = tx["shares"]
    price = tx.get("pricePerShare", "N/A")
    print(f"  {action}: {shares} shares @ ${price}")
Enter fullscreen mode Exit fullscreen mode

Response includes:

  • Transaction codes: P (Purchase), S (Sale), M (Option Exercise), G (Gift), A (Grant)
  • Insider roles: Director, Officer (with title), 10% Owner
  • Both non-derivative and derivative transactions (options, warrants)
  • Post-transaction holdings so you can see their total position

Build a Simple Alert Bot

Here's a practical example — a script that checks for large insider purchases and sends alerts:

import requests

API_URL = "https://sec-edgar-insider-alerts-production.up.railway.app"
WATCHLIST = ["AAPL", "MSFT", "GOOGL", "NVDA", "TSLA", "META", "AMZN"]
MIN_VALUE = 100000  # Alert on purchases over $100K

def check_insider_buys():
    alerts = []

    for ticker in WATCHLIST:
        resp = requests.get(f"{API_URL}/sec/insider-trades/company/{ticker}", params={
            "days": 1,
            "limit": 20
        })
        data = resp.json()

        for filing in data.get("filings", []):
            # Get full details to check transaction value
            detail = requests.get(f"{API_URL}{filing['detailUrl']}")
            info = detail.json()

            for tx in info.get("transactions", []):
                if tx["code"] == "P":  # Open market purchase
                    value = (tx.get("shares", 0) or 0) * (tx.get("pricePerShare", 0) or 0)
                    if value >= MIN_VALUE:
                        alerts.append({
                            "ticker": ticker,
                            "insider": info["owner"]["name"],
                            "shares": tx["shares"],
                            "value": value,
                            "date": tx["date"]
                        })

    return alerts

# Run it
buys = check_insider_buys()
for buy in buys:
    print(f"🚨 {buy['ticker']}: {buy['insider']} bought {buy['shares']} shares (${buy['value']:,.0f})")
Enter fullscreen mode Exit fullscreen mode

JavaScript Version (Node.js)

const API_URL = "https://sec-edgar-insider-alerts-production.up.railway.app";

// Fetch recent insider trades
async function getInsiderTrades(ticker, days = 7) {
  const res = await fetch(
    `${API_URL}/sec/insider-trades/company/${ticker}?days=${days}&limit=50`
  );
  const data = await res.json();

  return data.filings.map(f => ({
    date: f.filedDate,
    insider: f.insider.name,
    company: f.company.name,
    detailUrl: f.detailUrl
  }));
}

// Get transaction details
async function getFilingDetail(accession) {
  const res = await fetch(`${API_URL}/sec/insider-trades/filing/${accession}`);
  return res.json();
}

// Example: Find all purchases in NVDA this month
const trades = await getInsiderTrades("NVDA", 30);
console.log(`Found ${trades.length} NVDA insider filings`);

for (const trade of trades.slice(0, 5)) {
  console.log(`${trade.date}${trade.insider}`);
}
Enter fullscreen mode Exit fullscreen mode

Use Cases

  • Trading signals: Cluster analysis on insider buys (3+ insiders buying within a week is historically bullish)
  • Compliance dashboards: Monitor executive trading windows and blackout periods
  • Financial research: Backtest insider sentiment vs. stock performance
  • Slack/Discord bots: Push alerts when specific insiders trade
  • Portfolio screening: Filter your holdings by recent insider activity

Data Source & Reliability

The API pulls directly from SEC EDGAR's EFTS API and ATOM feed — official government data, not scraped from third-party sites. Polling happens every 5 minutes during market hours, with fallback to the ATOM feed if EFTS is down.

Covers all Form 4 filers across NYSE, NASDAQ, and OTC markets. No rate limiting on the direct endpoint.

Try It

The API is live and free to use:

No API key needed for the direct Railway endpoint. Just start making requests.

Top comments (0)