Query SEC annual revenue as of a filing date
Apply a filing-date cutoff and snapshot-pinned pagination to annual SEC revenue observations with Node.js.
Build a bounded observation export that excludes filings after an explicit cutoff and rejects a source refresh between pages. This is a filing-date selection from today’s source, not a reconstruction of an historical API response.
Requirements: Node.js 22 or later; no dependencies. 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.
const key = process.env.SEC_API_KEY;
if (!key) throw new Error("Set SEC_API_KEY");
const base = process.env.SEC_API_BASE_URL || "https://sec-api.dev";
async function request(path, params) {
const response = await fetch(base + path + "?" + new URLSearchParams(params), {
headers: {Authorization: "Bearer " + key}
});
if (!response.ok) throw new Error("HTTP " + response.status + ": " + await response.text());
return response.json();
}
const params = {taxonomy:"us-gaap", concept:"RevenueFromContractWithCustomerExcludingAssessedTax",
unit:"USD", period:"annual", asOf:"2025-12-31", limit:"5", offset:"0"};
const records = [];
let snapshot, nextOffset = 0, provenance;
for (let page = 0; page < 3 && nextOffset !== null; page++) {
const result = await request("/api/v1/financial-series/320193", {
...params, offset:String(nextOffset), ...(snapshot ? {snapshot} : {})
});
snapshot = result.meta.snapshotId;
provenance = result.meta;
for (const row of result.data) {
if (row.filed > params.asOf) throw new Error("Observation exceeds filing cutoff");
records.push(row);
}
nextOffset = result.pagination.nextOffset;
}
console.log(JSON.stringify({records, snapshot, provenance, hasMore:nextOffset !== null, nextOffset}, null, 2));What “as of” means here
The cutoff is inclusive and applies to the reported filing date. The endpoint selects among observations available in the current Company Facts source. It does not archive what the SEC API returned on the cutoff date, and it does not prove an observation was available before a particular intraday trading decision. Preserve the returned asOfScope and source retrieval time when documenting a study.
Keep exact periods and ambiguous values
Annual selection uses source durations of 330–380 days. The response groups exact start/end dates, chooses the latest eligible filing and retains its accession. If the selected filing has conflicting values, value is null and ambiguous is true. Do not replace that null with zero, sum overlapping periods, or assume one row per calendar year. Concept changes and issuer-specific extensions can leave gaps.
Stop when the source changes
The first response supplies a snapshot identifier; subsequent pages send it back. A 409 means the source snapshot changed and the export should restart from offset zero. The three-page budget is deliberate: hasMore and nextOffset disclose an unfinished export. Source snapshots support consistent pagination, not immutable permanent storage. Save the full output if you need a reproducible local artifact.
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.
- Financial series selection contract
- Inspect one page of annual observations
- Cutoff and snapshot parameters