SEC EDGAR's public data (no key): the ticker-to-CIK files,
submissions (company profile plus filing history), XBRL company
facts, company concepts and frames, filing indexes and document
URLs, EDGAR full-text search, and Form D notices of exempt offerings
(one filing's primary_doc.xml, a date-window listing, and SEC's
quarterly data sets).
User-Agent required. SEC rejects requests without a declared
User-Agent naming the company and a contact email, e.g. "Acme Corp ops@acme.com". Set sec.edgar.user-agent or pass
{user-agent: ...}; calls fail before any request when it is
missing.
Fair access: at most 10 requests per second per client across all of SEC's hosts. Exceeding it gets the client blocked for a while. Nothing here retries; pace bulk work with a schedule or tasks.
Hosts: www.sec.gov (ticker files, Archives), data.sec.gov
(submissions, XBRL APIs), efts.sec.gov (full-text search).
Context Vars
sec.edgar.user-agent
Values
DATA
DATA: Str "https://data.sec.gov"
EFTS
EFTS: Str "https://efts.sec.gov/LATEST"
FORM_D_TABLES
FORM_D_TABLES: Map {
submissions: "FORMDSUBMISSION",
issuers: "ISSUERS",
offerings: "OFFERING",
related-persons: "RELATEDPERSONS",
recipients: "RECIPIENTS",
signatures: "SIGNATURES"
}
SEARCH_WINDOW
SEARCH_WINDOW: Int 10000
WWW
WWW: Str "https://www.sec.gov"
Functions
accession-plain
fn (accession: Str): Str
An accession number without dashes, as used in Archives paths: "0000320193-24-000123" → "000032019324000123".
address
fn (node: Any): Map
amount
fn (v: Str?): Any
A Form D amount as an Int, or as filed when it isn't digits ("Indefinite"), or null when empty (pure).
cik-digits
fn (cik: Any): Str
The CIK's digits without leading zeros, as a Str ("0000320193", 320193 and "CIK320193" all give "320193"); an Err for anything else.
cik-for-ticker
fn (ticker: Str): Str?
fn (ticker: Str, opts: Map): Str?
The zero-padded CIK for a ticker, or null. Downloads the ticker file; when looking up many tickers, call company-tickers once and use find-ticker.
collect-form-d-filings
fn (start-date: Str, end-date: Str, limit: Int, opts: Map): Vec<Map>
Follow form-d-filings pages until limit rows or the last page,
one request per 100 rows, and at most the 10,000 rows EDGAR serves
for one search. An Err on any page is returned in place of the rows.
Example
rows ::sec::edgar/collect-form-d-filings("2026-10-30", "2026-10-30", 500, {})
collect-form-d-pages
fn (start-date: Str, end-date: Str, limit: Int, opts: Map, acc: Vec): Vec
company-concept
fn (cik: Any, taxonomy: Str, tag: Str): Map
fn (cik: Any, taxonomy: Str, tag: Str, opts: Map): Map
One concept's facts for a company, e.g. taxonomy "us-gaap", tag
"AccountsPayableCurrent": units.{unit}[] with end, val,
accn, fy, fp, form, filed.
company-concept-url
fn (cik: Any, taxonomy: Str, tag: Str): Str
company-facts
fn (cik: Any): Map
fn (cik: Any, opts: Map): Map
Every XBRL fact a company has reported (facts.{taxonomy}.{tag}.units.{unit}[]). Large filers' files run to several MB.
company-facts-url
fn (cik: Any): Str
company-tickers
fn (): Vec<Map>
fn (opts: Map): Vec<Map>
https://www.sec.gov/files/company_tickers.json as a Vec of
{cik, ticker, title} (about 10,000 listed companies, about 800 KB).
Fetch it once per run and reuse it; it changes daily.
element-texts
fn (nodes: Vec): Vec<Str>
elements
fn (node: Any): Vec
field
fn (node: Any, path: Vec<Str>): Str?
filing-document
fn (cik: Any, accession: Str, document: Str): Map
fn (cik: Any, accession: Str, document: Str, opts: Map): Map
Download one filing document as {content-type, bytes}. Large exhibits can exceed http.max-response-bytes.
filing-document-url
fn (cik: Any, accession: Str, document: Str): Str
The URL of one document in a filing, e.g. its primaryDocument
from recent-filings.
Example
::sec::edgar/filing-document-url(320193, "0000320193-24-000123", "aapl-20240928.htm")
// "https://www.sec.gov/Archives/edgar/data/320193/000032019324000123/aapl-20240928.htm"
filing-folder-url
fn (cik: Any, accession: Str): Str
The Archives folder of a filing: https://www.sec.gov/Archives/edgar/data/{cik}/{accession without dashes}.
filing-index
fn (cik: Any, accession: Str): Map
fn (cik: Any, accession: Str, opts: Map): Map
A filing folder's index.json listing (directory.item[] with name, type, size, last-modified).
filing-index-url
fn (cik: Any, accession: Str): Str
The human-readable filing index page: .../{accession}-index.htm.
find-ticker
fn (tickers: Vec<Map>, ticker: Str): Map?
The {cik, ticker, title} for a ticker (case-insensitive) in a ticker list, or null (pure).
flag
fn (node: Any, path: Vec<Str>): Bool?
form-d
fn (cik: Any, accession: Str): Map?
fn (cik: Any, accession: Str, opts: Map): Map?
Read one Form D filing: parse-form-d of its primary_doc.xml,
plus accession and url. Null when the filing has no such document
(the 404 for a paper filing or a wrong accession number). An Err for
a CIK that isn't one.
Any CIK on the filing works, so rows from recent-filings and
form-d-filings both lead here.
Example
subs ::sec::edgar/submissions(2162876)
row first(::sec::edgar/recent-filings(subs, 1, {forms: ["D", "D/A"]}))
d ::sec::edgar/form-d(subs.cik, row.accessionNumber)
d.issuer.name
d.total-offering-amount
form-d-dataset
fn (year: Int, quarter: Int): Map?
fn (year: Int, quarter: Int, opts: Map): Map?
One quarter of SEC's Form D data sets: every Form D filed in the
quarter as flat tables. Two requests, the data sets page and the zip
(about 4 MB). Returns {year, quarter, url, ...tables}, or null when
SEC hasn't posted that quarter. opts.tables is as in
parse-form-d-dataset.
SEC updates the data sets quarterly, and says the values are as filed and that it can't guarantee their accuracy.
Example
d ::sec::edgar/form-d-dataset(2026, 3, {tables: ["offerings"]})
length(d.offerings)
form-d-dataset-url
fn (html: Str, year: Int, quarter: Int): Str?
A quarter's zip URL from the HTML of SEC's Form D data sets page, or
null when the page doesn't list it (pure). The URLs can't be built:
the folder has changed over the years and some names end _d_0.zip.
form-d-datasets-page-url
fn (): Str
form-d-fields
fn (root: Any): Map
form-d-filing
fn (hit: Map): Map
One full-text search hit as a row (pure): {accession, form, filed, ciks, names, file-numbers, exemptions, url}. url is form-d-url
for the first CIK, and exemptions are upper-cased by the index
("06B", where the filing says "06b").
form-d-filings
fn (start-date: Str, end-date: Str): Map
fn (start-date: Str, end-date: Str, opts: Map): Map
One page (100 rows, newest first) of the Form D filings in a date
window, through full-text-search. Returns {total, total-is-exact, from, filings, next-from}; pass next-from as opts.from for the
next page. It is null on the last page.
forms defaults to ["D"], and that lists amendments too. EDGAR
matches forms=D on the root form, so it returns both D and D/A,
while forms=D,D/A returns only the D/A filings. opts.forms: ["D/A"] narrows to amendments. Keep originals alone by filtering on
form.
EDGAR serves the first 10,000 hits of a search and no further; past
that total stops at 10,000 and total-is-exact is false. A quarter
has more than that, so use narrower windows, or form-d-dataset.
opts also takes ciks, and anything else full-text-search does.
Example
page ::sec::edgar/form-d-filings("2026-10-20", "2026-10-31")
page.total
first(page.filings).url
form-d-issuer
fn (node: Any): Map
form-d-page
fn (body: Map, from: Int): Map
A full-text search body as {total, total-is-exact, from, filings, next-from} (pure). from is the offset it was asked for.
form-d-person
fn (node: Any): Map
form-d-recipient
fn (node: Any): Map
form-d-signature
fn (node: Any): Map
form-d-table
fn (archive: Bytes, names: Vec<Str>, table: Str): Vec<Map>
form-d-url
fn (cik: Any, accession: Str): Str
The URL of a Form D filing's XML, primary_doc.xml in the filing
folder. Use this rather than the url from recent-filings: the
primaryDocument of a Form D is xslFormDX01/primary_doc.xml, the
same filing rendered as HTML.
Example
::sec::edgar/form-d-url(2162876, "0002162876-26-000002")
// "https://www.sec.gov/Archives/edgar/data/2162876/000216287626000002/primary_doc.xml"
frames
fn (taxonomy: Str, tag: Str, unit: Str, period: Str): Map
fn (taxonomy: Str, tag: Str, unit: Str, period: Str, opts: Map): Map
One fact across all companies for a period: the latest value each filer reported that best fits the calendar period.
Example
f ::sec::edgar/frames("us-gaap", "AccountsPayableCurrent", "USD", "CY2019Q1I")
length(f.data)
frames-url
fn (taxonomy: Str, tag: Str, unit: Str, period: Str): Str
/api/xbrl/frames/{taxonomy}/{tag}/{unit}/{period}.json, e.g. period "CY2019Q1I" (instant) or "CY2023" (annual). Units with a slash such as USD/shares are written USD-per-shares.
full-text-params
fn (q: Str, opts: Map): Map
Query parameters for EDGAR full-text search (pure). opts: forms
(Vec or comma list), start-date / end-date (YYYY-MM-DD, sets
dateRange=custom), ciks, from (offset; pages are 100 hits).
Unset options are omitted.
full-text-search
fn (q: Str): Map
fn (q: Str, opts: Map): Map
EDGAR full-text search (filings since 2001) via
efts.sec.gov/LATEST/search-index, the endpoint behind the EDGAR
full-text search web page. SEC does not document it as a public
API, so its shape can change.
Returns the raw Elasticsearch-style body: hits.total.value and
hits.hits[]._source with ciks, display_names, form,
file_date, adsh (accession) and more. Wrap phrases in double
quotes.
Example
res ::sec::edgar/full-text-search("\"climate risk\"", {forms: ["10-K"], start-date: "2025-01-01", end-date: "2025-03-31"})
res.hits.total.value
headers
fn (opts: Map): Map
The SEC request headers (User-Agent from settings), or an Err when no user-agent is set.
kid
fn (node: Any, tag: Str): Any
kids
fn (node: Any, tag: Str): Vec
pad-cik
fn (cik: Any): Str
A CIK zero-padded to the ten digits EDGAR's JSON APIs use.
Example
::sec::edgar/pad-cik(320193) // "0000320193"
::sec::edgar/pad-cik("CIK0000320193") // "0000320193"
parse-form-d
fn (text: Str): Map
A Form D primary_doc.xml as a Map (pure). The main fields:
form("D"or"D/A"),is-amendment,previous-accessionissuer, the primary issuer, andissuers, all of them with the primary first:{cik, name, address, phone, jurisdiction, entity-type, entity-type-other, year-of-inc, year-of-inc-choice, previous-names}related-persons:[{name, first-name, middle-name, last-name, address, relationships, clarification}]exemptions, as filed:["06b", "3C", "3C.1"]first-sale-date(YYYY-MM-DD), null whenfirst-sale-yet-to-occuris truetotal-offering-amount,total-amount-sold,total-remaining: an Int, or"Indefinite"minimum-investment,sales-commissions,finders-fees,gross-proceeds-used,total-investors,has-non-accredited-investors,non-accredited-investorsindustry-group,investment-fund-type,is-40-act,revenue-range,net-asset-value-range,security-types,more-than-one-year,business-combinationsales-compensation:[{name, crd, broker-dealer, broker-dealer-crd, address, states, foreign-solicitation}]signatures:[{issuer-name, signature, signer, title, date}]
An element the filing leaves out is null. An Err for malformed XML, and for XML that isn't a Form D.
parse-form-d-dataset
fn (archive: Bytes): Map
fn (archive: Bytes, opts: Map): Map
Read tables from a quarterly data set zip as Bytes (pure). Returns a
Map of table name to rows, keyed by SEC's column names (see the
FormD_readme.html in each zip), with every value a Str.
opts.tables picks from submissions, issuers, offerings,
related-persons, recipients and signatures. It defaults to
submissions, issuers and offerings, leaving out the three
tables of people, which are the bulk of the data.
Rows of one filing share ACCESSIONNUMBER across tables.
parse-tickers
fn (body: Any): Vec<Map>
{"0": {cik_str, ticker, title}, ...} → [{cik, ticker, title}] with cik zero-padded (pure).
previous-names
fn (node: Any, tag: Str): Vec<Str>
read-form-d-tables
fn (archive: Bytes, names: Vec<Str>, tables: Vec<Str>, acc: Map): Map
recent-filings
fn (subs: Map, limit: Int, opts: Map): Vec<Map>
filings.recent of a submissions body as rows (pure): [{accessionNumber, filingDate, form, primaryDocument, ...}], newest first, at most
limit. Each row also gets url, the primary document's URL.
opts.forms keeps only those form types (e.g. ["10-K", "10-Q"]).
search-tickers
fn (tickers: Vec<Map>, name: Str, limit: Int): Vec<Map>
Ticker-list rows whose company name contains name (case-insensitive), at most limit (pure).
sec-get
fn (url: Str, opts: Map): Any
security-types
fn (offering: Any): Vec<Str>
submissions
fn (cik: Any): Map
fn (cik: Any, opts: Map): Map
data.sec.gov/submissions/CIK##########.json: the company profile
(name, tickers, exchanges, SIC, state of incorporation, fiscal year
end, addresses, former names) and its most recent filings (at least
a year, up to 1,000) in filings.recent, with older pages listed in
filings.files.
Example
sub ::sec::edgar/submissions(320193)
sub.name // "Apple Inc."
submissions-page
fn (file-name: Str): Map
fn (file-name: Str, opts: Map): Map
One older submissions page named in filings.files (e.g. "CIK0000320193-submissions-001.json"); its columns are the same as filings.recent.
submissions-url
fn (cik: Any): Str