EDGAR is free, but it isn't one API
The SEC publishes three useful surfaces, each with its own shape:
-
Submissions — a company's full filing history (
data.sec.gov/submissions/CIK##########.json). -
Company facts — XBRL financial values (
companyfacts), per concept. -
Full-text search —
efts.sec.govacross all filings.
The SEC EDGAR API Actor wraps all three behind one input and emits one row schema.
Three modes
{ "queries": ["AAPL"], "mode": "filings", "formTypes": ["10-K"], "maxFilingsPerCompany": 4 }
{ "queries": ["TSLA"], "mode": "facts", "concepts": ["Revenues", "NetIncomeLoss"], "unitsFilter": "USD" }
{ "queries": ["\"generative AI\""], "mode": "search", "searchForms": ["10-K"], "maxSearchHits": 50 }
A filing row
{
"recordType": "filing",
"cik": "0001045810",
"entityName": "NVIDIA CORP",
"ticker": "NVDA",
"accessionNumber": "0001045810-26-000021",
"formType": "10-K",
"filingDate": "2026-02-25",
"reportDate": "2026-01-25",
"primaryDocument": "nvda-20260125.htm",
"filingUrl": "https://www.sec.gov/Archives/edgar/data/...",
"isXBRL": true,
"isInlineXBRL": true
}
Facts rows carry the concept, unit, value, period and the accession that reported it — so a number is always traceable to a filing.
One caveat on the facts mode: companyfacts returns every value as reported in every filing, so the same period appears several times. Each 10-K repeats the prior years, each 10-Q repeats last year's quarter, and a 10-Q carries both the quarter and the year-to-date total under one concept. Filter on the frame field (for example CY2025Q3) to keep one value per calendar period; otherwise compare start and end dates to tell a quarter from a year-to-date figure before charting anything. Credit to reader Daniel O. for calling this out.
Why use an Actor for this
- Polite by default: the Actor sends a declared user agent with contact info, as the SEC requires.
- Joins the tedious bits: ticker → CIK lookup, pagination, concept filtering, unit filtering.
-
Error rows, not failures: an unknown ticker becomes an
ok:falserow with a hint instead of killing the run.
Try it
SEC EDGAR API: Filings & XBRL Financials — no API key.
Top comments (2)
One caveat worth adding for the facts mode: companyfacts returns every value as reported in every filing, so the same period appears several times (each 10-K repeats the prior years, each 10-Q repeats last year's quarter), and a 10-Q carries both the quarter and the year-to-date total under one concept. Filtering on the
framefield (for exampleCY2025Q3) keeps one value per calendar period; otherwise comparestartandendto tell a quarter from a year-to-date figure before charting anything.Disclosure: I build Equibles, which does this normalization for US companies behind an MCP server and a REST API.
Filtering on
framehas one catch that matters if the numbers feed a backtest: the frame tag is attached to a single copy of each period, the most recently filed one. Apple's FY2023 NetIncomeLoss (2022-09-25 to 2023-09-30, 96,995,000,000) appears in three 10-Ks: filed 2023-11-03, 2024-11-01 and 2025-10-31. Only the last carriesframe: CY2023; the first two have none. So a frame filter returns the right value, but with a filing date two years after the number was public, and any "as known on date X" logic built on it looks ahead.Two more things to handle before charting. The fiscal Q4 three-month fact (2023-07-02 to 2023-09-30) doesn't exist for Apple at all, because the 10-K only reports the full year; Q4 has to be derived as FY minus the nine-month year-to-date, and that subtraction needs both facts from compatible filings. And for point-in-time work, keep
filednext toendand take, per period, the earliestfiledcopy (or the latest one on or before the as-of date) instead of the framed one.