Select annual SEC revenue observations with JavaScript

Request exact annual periods, detect conflicting selected-filing values and preserve source provenance without inventing quarterly totals.

WHAT YOU WILL BUILD

Use an exact taxonomy, concept and unit to select observations by duration. Keep conflict flags and source links; a null ambiguous value must not silently become zero.

Requirements: Node.js22 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.

// 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 params = new URLSearchParams({
  taxonomy: "us-gaap",
  concept: "RevenueFromContractWithCustomerExcludingAssessedTax",
  unit: "USD", period: "annual", limit: "100"
});
const result = await request("/api/v1/financial-series/320193?" + params);
for (const observation of result.data) {
  console.log(JSON.stringify({
    start: observation.start, end: observation.end,
    value: observation.value, unit: observation.unit,
    ambiguous: observation.ambiguous,
    conflictingValues: observation.conflictingValues,
    observationsCompared: observation.observationCount,
    sourceFiling: observation.filingUrl
  }));
}
console.log(JSON.stringify({
  source: result.meta.source, snapshot: result.meta.snapshotId,
  nextOffset: result.pagination.nextOffset,
  selection: result.meta.selection
}));
// If nextOffset is non-null, pass both offset and snapshot on the next request.
// A 409 means the selection changed: restart instead of mixing snapshots.

Exact periods before fiscal labels

Annual mode selects330–380-day durations and groups exact start/end dates. Fiscal labels describe the reporting filing, so use the actual observation period for comparisons.

Restatements and conflict signals

The latest filing date wins within each period, with accession as tie-breaker. Multiple values in the selected filing yield null and ambiguous:true. Distinct source values and observation counts remain visible.

A cutoff is not a historical capture

Optional asOf limits reported filing dates. It does not reconstruct which records the SEC API exposed on a past day. No missing fourth-quarter value is derived and no segment dimensions are added.

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 ←