Insights
Structured SEC 8-K Cyber Incident Data
Alphanume Team · August 10, 2026
Structured SEC 8-K cyber incident data turns each Item 1.05 filing and 8-K/A amendment into a dated row with distinct incident clocks, three-state disclosure flags, amendment linkage, and the original EDGAR source.
Alphanume's Cyber Incidents endpoint covers material cybersecurity disclosures filed under Item 1.05 since that item took effect on December 18, 2023. The route is GET /v1/regulatory/cyber-incidents, and one row represents one filing. Original 8-Ks and later 8-K/A amendments remain separate records.
That normalized layer answers questions a raw text search leaves unresolved. A phrase match can find ransomware, yet it does not reliably separate discovery, materiality determination, filing acceptance, and amendment dates. It also tends to flatten silence into no. The structured record preserves those differences and carries filing_url so every extracted claim can be checked against EDGAR.
Keep four clocks separate
Field | What it dates | Important treatment |
|---|---|---|
incident_discovered_date | When the filing says the incident was discovered | Check its precision companion before assuming an exact day |
materiality_determined_date | When the company says it judged the incident material | Often unstated and therefore null |
disclosed_date | EDGAR filing date for this record | Equals date on original filings |
filing_timestamp | Exact EDGAR acceptance timestamp with offset | Use to choose same-session or next-session price windows |
amended_date | Filing date of an 8-K/A | Null on original filings |
Each extracted incident date has a precision value such as day, month, quarter, year, or unstated. Imprecise values are normalized to the first day of the stated period, so a month-precision date should not enter a day-level latency calculation without a sensitivity rule.
The Cyber Incidents field reference documents the filters and all served fields. Date filters act on the disclosure date of the specific filing, which means an amendment range retrieves amendment filings rather than silently replacing their originals.
Build the Item 1.05 cohort
For a first-disclosure cohort, query is_amendment=0, preserve refused rows, and paginate until has_more is false. Keyset pagination uses cursor_date and cursor_accession, both copied from the response cursor. The underlying ordering is disclosure date descending and accession number ascending.
import os
import requests
url = "https://api.alphanume.com/v1/regulatory/cyber-incidents"
headers = {"X-API-Key": os.environ["ALPHANUME_API_KEY"]}
params = {"date_gte": "2023-12-18", "is_amendment": "0"}
rows = []
while True:
response = requests.get(url, headers=headers, params=params, timeout=30)
response.raise_for_status()
payload = response.json()
rows.extend(payload["data"])
if not payload.get("has_more"):
break
cursor = payload["next_cursor"]
params.update({
"cursor_date": cursor["date"],
"cursor_accession": cursor["accession_number"],
})
assert len({row["accession_number"] for row in rows}) == len(rows)The corpus is small because Item 1.05 is recent and material incident disclosures are rare. A thin filtered cohort can be the correct population. Avoid importing older press-release incidents into the denominator unless the project explicitly creates and labels a second source.
Read flags as disclosure facts
Value | Meaning | Research rule |
|---|---|---|
1 | The filing states yes | Include in a stated-yes cohort |
0 | The filing states no | Keep separate from silence |
null | The filing does not say | Preserve as unknown |
refused = 1 | The labeler declined the filing text | Retain the disclosure event and treat extracted fields as unavailable |
The three-state rule applies to data compromise, operational disruption, third-party origin, containment, restoration, ongoing investigation, and law-enforcement notification. Only the first three are available as server-side filters. A query for flag 0 and a query for flag 1 will not sum to the unfiltered count because silent filings match neither.
Likewise, is_amendment means this row is an 8-K/A. amended_flag belongs to an original and says a later amendment exists. It is null on amendment rows because the field does not apply there.
Free access exposes a trailing 20-trading-session window delayed by one trading session. Building the full Item 1.05 population from December 2023 requires historical access, so a restricted-range response should remain separate from a valid zero-row result.
Amendments change what is known
Amendment linkage fields can update after an original row was first served. Save original rows as initially observed, then poll updated_since against last_updated and store revisions separately. Overwriting the old record leaks a later amendment backward into the first-disclosure cohort.
- Severity inference. A disclosed flag describes what the company stated and cannot establish undisclosed damage, causation, or expected returns.
- Sparse materiality dates. Missing determination dates prevent exact compliance-interval calculations.
- Calendar versus business days.
days_determination_to_disclosureuses calendar days, so a value above four does not establish a late filing. - Ticker gaps. Some filers lack a ticker; CIK is the identifier present on every row.
- After-close timing. Event windows must use
filing_timestamp, not a date-only merge.
Run a source-audited slice
Pull original filings, export the raw response, and build a table containing accession number, CIK, filing timestamp, all four date roles, their precision fields, attack type, three-state flags, refused status, and filing URL. Check every included incident against its filing URL before attaching returns.
Explore the normalized record on the Cyber Incidents dataset page. Then create a second amendment table keyed by original_accession_number, and report unlinked amendments rather than guessing which original they revise.