How to monitor 8-K filings in real time
8-K filings announce material events the moment they happen — earnings surprises, CEO departures, major contracts. This guide shows you how to subscribe to 8-K filings for a list of tickers, filter to the item numbers you actually care about, and receive a real-time push via webhook or poll on a tight schedule.
The problem
An 8-K can move a stock before any analyst publishes a note. The window between SEC acceptance and widespread awareness is often measured in seconds, not minutes. Polling EDGAR directly is possible, but their index files update in batches and their per-filing endpoints are rate-limited at 10 requests per second per IP.
The three item numbers that drive most of the alpha-relevant 8-Ks are:
- Item 5.02 — departure or appointment of directors and principal officers (CEO/CFO changes)
- Item 2.02 — results of operations (earnings releases, guidance updates)
- Item 1.01 — entry into a material definitive agreement (major contracts, partnerships, M&A)
Catching those three within seconds of filing is the whole task.
The approach
EdgarKit gives you two paths:
- Webhook — register an endpoint and EdgarKit pushes each matching filing to you as it's accepted. Best for production.
- Polling — hit the REST API on a schedule. Easier to prototype; fine for workflows where a 1-5 minute lag is acceptable.
This guide covers both. The webhook approach is the right long-term choice.
Step 1: Register a webhook for 8-K filings
Send a POST to /v1/webhooks with the form types and tickers you want to watch. You can also pass item_numbers to restrict to specific 8-K sections.
curl -X POST "https://api.edgarkit.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/sec-filings",
"form_types": ["8-K"],
"tickers": ["NVDA", "AAPL", "TSLA"],
"item_numbers": ["5.02", "2.02", "1.01"],
"secret": "your_webhook_signing_secret"
}'
The response includes a webhook_id you'll use to update or delete the subscription later:
{
"webhook_id": "wh_a1b2c3d4e5",
"status": "active",
"url": "https://your-server.com/webhooks/sec-filings",
"form_types": ["8-K"],
"tickers": ["NVDA", "AAPL", "TSLA"],
"item_numbers": ["5.02", "2.02", "1.01"],
"created_at": "2026-06-18T12:00:00Z"
}
Keep the secret value in your environment variables. EdgarKit uses it to sign every payload so you can verify it's actually from us — the webhook verification guide walks through the HMAC check.
Step 2: Understand the webhook payload shape
When a matching 8-K is accepted by the SEC, EdgarKit delivers a POST to your URL within seconds. Here's what the payload looks like:
{
"event": "filing.new",
"filing": {
"id": "8k_0001234567_20260618",
"form_type": "8-K",
"issuer_ticker": "NVDA",
"issuer_name": "NVIDIA Corporation",
"issuer_cik": "0001045810",
"filed_at": "2026-06-18T14:32:11Z",
"period_of_report": "2026-06-18",
"item_numbers": ["2.02", "9.01"],
"accession_number": "0001045810-26-000123",
"primary_document_url": "https://www.sec.gov/Archives/edgar/data/1045810/000104581026000123/nvda8k.htm",
"filing_index_url": "https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001045810"
},
"webhook_id": "wh_a1b2c3d4e5",
"delivered_at": "2026-06-18T14:32:14Z"
}
The item_numbers array contains every item declared in the filing. A single 8-K often covers multiple items (here, 2.02 earnings plus 9.01 financial statements). Your handler can match on whichever items you care about.
Step 3: Poll the API as an alternative
If you're not ready to expose a webhook endpoint, polling is a perfectly workable approach. Hit /v1/filings every 60 seconds with a since timestamp:
curl "https://api.edgarkit.com/v1/filings?form_type=8-K&ticker=NVDA,AAPL,TSLA&item_numbers=5.02,2.02,1.01&since=2026-06-18T14:00:00Z&limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"
Store the filed_at of the most recent result and use it as since on the next poll to avoid re-processing.
Step 4: Handle a 5.02 executive-change filing
Item 5.02 filings are particularly time-sensitive. Here's a minimal Python handler that checks incoming webhook payloads for 5.02 and logs the alert:
import hmac
import hashlib
import json
import os
from datetime import datetime
SIGNING_SECRET = os.environ["EDGARKIT_WEBHOOK_SECRET"]
def handle_payload(raw_body: bytes, signature_header: str) -> None:
# Verify signature first (always do this before processing)
expected = "sha256=" + hmac.new(
SIGNING_SECRET.encode(), raw_body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature_header):
raise ValueError("Invalid webhook signature")
payload = json.loads(raw_body)
filing = payload["filing"]
if "5.02" in filing.get("item_numbers", []):
print(
f"[{datetime.utcnow().isoformat()}] EXEC CHANGE: "
f"{filing['issuer_ticker']} filed 8-K item 5.02 "
f"at {filing['filed_at']} — {filing['primary_document_url']}"
)
The HMAC verification step is non-optional. Anyone who knows your webhook URL could POST fake payloads without it.
Putting it together
Here's a complete Python polling script that checks every 60 seconds and fires an alert on matching 8-Ks:
import os
import time
import requests
from datetime import datetime, timezone
API_KEY = os.environ["EDGARKIT_API_KEY"]
BASE_URL = "https://api.edgarkit.com/v1/filings"
TICKERS = ["NVDA", "AAPL", "TSLA"]
ITEM_NUMBERS = ["5.02", "2.02", "1.01"]
POLL_INTERVAL = 60 # seconds
def poll(since: str) -> tuple[list[dict], str]:
params = {
"form_type": "8-K",
"ticker": ",".join(TICKERS),
"item_numbers": ",".join(ITEM_NUMBERS),
"since": since,
"limit": 50,
}
resp = requests.get(
BASE_URL,
params=params,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10,
)
resp.raise_for_status()
data = resp.json()
filings = data["filings"]
new_since = filings[0]["filed_at"] if filings else since
return filings, new_since
def main():
since = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
print(f"Polling for 8-Ks on {', '.join(TICKERS)} since {since}")
while True:
try:
filings, since = poll(since)
for f in filings:
items = ", ".join(f.get("item_numbers", []))
print(f"[{f['filed_at']}] {f['issuer_ticker']} 8-K — items: {items}")
print(f" {f['primary_document_url']}")
except Exception as e:
print(f"Poll error: {e}")
time.sleep(POLL_INTERVAL)
if __name__ == "__main__":
main()
FAQ
What's the difference between item 2.02 and item 2.01?
Item 2.02 is results of operations — it's the earnings press release wrapper. Item 2.01 is completion of an acquisition or disposition, which is an M&A event. They're easy to mix up; always check the item number, not just the form type.
Can I subscribe to all 8-Ks without filtering by item number?
Yes. Omit the item_numbers field from your webhook registration or polling request. You'll receive every 8-K for your tickers, including boilerplate filings like Item 8.01 (other events) and Item 9.01 (financial statements). Volume goes up significantly for active tickers.
How quickly does an 8-K appear after the company files it?
EdgarKit picks up new filings within roughly 30 seconds of SEC acceptance. The SEC itself typically accepts a filing within a few minutes of submission, so the end-to-end latency from submission to your webhook is usually under 5 minutes.
What happens if my webhook endpoint is down when a filing comes in?
EdgarKit retries failed deliveries with exponential backoff over 24 hours. If your endpoint returns a non-2xx status, the delivery is queued for retry. You can also fetch missed filings retroactively via the polling endpoint using a since timestamp.
Can I filter to a specific executive role in a 5.02 filing?
The item number filter only tells you a 5.02 was filed. To know whether it's a CEO departure versus a board addition, you need to read the filing text itself. Pull primary_document_url and parse the HTML, or check our structured fields in the details object returned with each 8-K (available for common 5.02 patterns).