Find recent SEC filings from a ticker with JavaScript
Build a two-request Node.js workflow: resolve a ticker to a CIK, filter recent SEC filings by form, and retain the original document links and source metadata.
Resolve an exact ticker match from the company directory, then pass its CIK to the filings endpoint. The example prints recent 10-K metadata and original SEC document links without pretending to retrieve the full historical archive.
Requirements: Node.js 22 or later; no extra packages. An API key from your dashboard, stored in the SEC_API_KEY environment variable.
Run the workflow
Save this as workflow.mjs and run node workflow.mjs. The production base URL is used by default. Keep credentials out of source control.
// Node.js 22+. Set SEC_API_KEY before running.
const key = process.env.SEC_API_KEY;
if (!key) throw new Error("Set SEC_API_KEY first");
const base = process.env.SEC_API_BASE_URL || "https://sec-api.dev";
async function request(path) {
const response = await fetch(base + path, {
headers: { Authorization: "Bearer " + key }
});
if (!response.ok) {
throw new Error("HTTP " + response.status + ": " + await response.text());
}
return response.json();
}
const ticker = "AAPL";
const lookup = await request("/api/v1/companies?" + new URLSearchParams({
query: ticker, limit: "20"
}));
const company = lookup.data.find(row => row.ticker.toUpperCase() === ticker);
if (!company) throw new Error("No exact ticker match in the current directory");
const filings = await request("/api/v1/filings?" + new URLSearchParams({
cik: company.cik, form: "10-K", limit: "5"
}));
console.log(JSON.stringify({
company,
filings: filings.data.map(row => ({
accessionNumber: row.accessionNumber,
filingDate: row.filingDate,
reportDate: row.reportDate,
documentUrl: row.documentUrl
})),
mappingSource: lookup.meta,
filingSource: filings.meta,
pagination: filings.pagination
}, null, 2));Choose an exact match before making the second request
The first response is a search result, not a single authoritative answer to every ticker-like input. The example normalizes its own requested ticker and checks the returned ticker explicitly. If there is no exact match, it stops instead of silently using a company whose name happens to contain the same letters. This is a useful boundary for a ticker-specific application. For an interactive name search, show the candidate list to your user and let them choose the entity instead. Preserve the returned padded CIK as a string for the next request.
Filter before presenting a filing list
The second call asks for the selected issuer’s 10-K records. A 10-K/A amendment is a different exact form value and is not automatically included. This tutorial deliberately prints the report date beside the filing date so the two are not confused. It also retains the accession number: the document URL is convenient for a reader, while the accession remains useful when reconciling stored records. A null document URL should stay visibly unavailable rather than being replaced with a guessed path.
Show the response boundary
The example retrieves one page of the default recent dataset. Inspect pagination and the historyCoverage field instead of labeling five returned rows as the company’s entire reporting history. If you add pagination, follow nextOffset until null and deduplicate accession numbers. A source refresh can shift offsets between requests. Choose a history retrieval mode only after reviewing its documented scope and limits; the two-call example intentionally keeps the default behavior so its result is easy to understand.
Turn the output into a useful interface
Display the company name, form, filing date, and a link to the original document. Keep mappingSource and filingSource in your application’s diagnostics, because the ticker lookup and submissions list are separate source resources with separate retrieval times. Show a stale notice when the source metadata says the cached response is stale. Catch non-success status codes before rendering rows. A failed request is not an empty filing list, and the absence of one form from the current result should not be presented as proof that the issuer never filed it.
Sources and further reading
The underlying SEC dataset behavior is documented in the official SEC API reference and SEC technical specifications. Response-field names shown here belong to the sec-api.dev endpoint contract. The scripts print actual results and do not embed fabricated filing or financial data.
All tutorials ←