# SEC Filing Alerts - 8-K, Form 4, 13D & 10-K Monitor (`skillmerc/sec-filing-alerts`) Actor

Get alerted when your tickers file with the SEC: 8-K items, Form 4 insider trades, 13D/13G, 10-K, 10-Q, S-1. Runs on a schedule, sends to Slack or a webhook, $0.01 per new filing.

- **URL**: https://apify.com/skillmerc/sec-filing-alerts.md
- **Developed by:** [Kyle Pretorius](https://apify.com/skillmerc) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 alerts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SEC Filing Alerts

Watch a list of tickers or CIKs on SEC EDGAR and get told only when a new filing appears. Each run reads the official submissions feed for every company, compares it against the snapshot from the previous run, and writes one row per new filing that matches your filters: form types such as 8-K, 10-K, 10-Q, Form 4, SC 13D, SC 13G, S-1 or DEF 14A, and optionally specific 8-K items such as 5.02 (officer and director changes) or keywords.

Nothing new was filed? The run writes nothing and you pay almost nothing. Data comes from `data.sec.gov`, the SEC's official JSON API. No API key, no login.

### Common uses

- Event trading and research: hear about 8-K items such as 5.02 (executive changes) or 1.01 (material agreements) soon after filing.
- Insider activity: Form 4 filings for the companies you follow.
- Activist watch: new SC 13D and 13G filings on your holdings.

### How to schedule it

1. Run the actor once with your companies, form types and a `watchlistName`. The first run saves a baseline and reports nothing, unless you set `initialLookbackDays` (see below).
2. In Apify Console open the actor, click Schedule, and pick an interval. EDGAR accepts filings on business days from 6:00 to 22:00 US Eastern time. Every 30 or 60 minutes during that window catches 8-Ks the same day; once a day is fine for periodic reports.
3. Optional: put a Slack incoming webhook URL or your own HTTPS endpoint in the input to receive each run's alerts as a push message.

Every scheduled run reuses the same `watchlistName`, so it always compares against the previous run. The snapshot lives in a key-value store named `sec-filing-alerts-<watchlistName>` in your account. Delete that store to start over.

If you leave `watchlistName` empty, the name is derived from the list of companies, so editing the list starts a fresh baseline. Naming the watchlist is better.

### Initial lookback

Set `initialLookbackDays` to a number such as 30 and the first run also reports filings dated within that window that match your filters. This gives you a useful first result immediately and lets you check the output before scheduling. Later runs ignore the setting and report only filings that are new since the previous run.

### Filters

- `formTypes`: exact form names as EDGAR uses them. `4` is Form 4, `SC 13D` and `SC 13G` are the ownership schedules; `13D/G` is accepted as shorthand for both. Empty means every form.
- `includeAmendments`: when true (default), `10-K/A` is reported if `10-K` is selected, and so on.
- `items8K`: item numbers that an 8-K must contain, for example `5.02`, `1.01`, `2.02`, `8.01`. Only 8-K filings are affected; other forms pass through.
- `keywords`: case-insensitive words matched against the form type, the 8-K item list and the primary document description.

The snapshot always stores the full filing list, so changing filters later never resurfaces old filings as new.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `companies` | array | | Tickers (`AAPL`) or CIK numbers (`320193`). |
| `formTypes` | array | `[]` (all) | Form types to alert on. |
| `includeAmendments` | boolean | `true` | Also report `/A` amendments of selected forms. |
| `items8K` | array | `[]` | 8-K item numbers to require. |
| `keywords` | array | `[]` | Keywords to require. |
| `initialLookbackDays` | integer | `0` | On the first run, also report filings dated within this many days. |
| `watchlistName` | string | | Name of the watchlist. Keeps the snapshot between runs. |
| `webhookUrl` | string | | HTTPS endpoint that receives a JSON POST per run with the summary and alerts. |
| `slackWebhookUrl` | string | | Slack incoming webhook. One message per run. |
| `maxAlertsPerRun` | integer | `500` | Upper bound on alerts delivered and charged in a single run. |

### Output

One dataset row per new filing. Example (a real row from a test run):

```json
{
  "watchlist": "my-watchlist",
  "change_type": "new_filing",
  "cik": "1318605",
  "ticker": "TSLA",
  "company_name": "Tesla, Inc.",
  "form_type": "8-K",
  "filing_date": "2026-10-02",
  "accepted_at": "2026-10-02T13:04:26.000Z",
  "report_date": "2026-10-02",
  "items": ["2.02", "9.01"],
  "description": "8-K",
  "summary": "TSLA: new 8-K (items 2.02, 9.01) filed 2026-10-02 - 8-K",
  "accession_number": "0001628280-26-064366",
  "filing_url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026064366/",
  "document_url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026064366/tsla-20261002.htm",
  "size": 156965,
  "detected_at": "2026-10-06T07:05:04.956Z",
  "run_id": "abc123"
}
```

If a registrant changes its name between runs you also get a `name_change` row with `before` and `after`.

The run stores a summary in the `OUTPUT` record of the run's key-value store: `companies_checked`, `changes_detected`, `alerts_delivered`, `alerts_skipped`, `not_found` and whether the run was a baseline.

### Webhook payloads

`webhookUrl` receives one POST per run: the summary plus `run_id` and an `alerts` array of the rows. Nothing is sent when a run has no alerts (except the first baseline run, which sends the summary).

`slackWebhookUrl` receives a short message listing up to 20 filings with document links.

### Pricing

You pay per alert, not per company. Each new filing row written to the dataset costs USD 0.01. Each run also costs USD 0.001 to start, which covers checking your whole list when nothing new was filed. Platform usage is included.

Example: a watchlist of 20 companies on 8-K, 10-K and 10-Q, checked hourly on business days (about 350 runs a month), with 40 new filings a month, costs about USD 0.40 for the alerts plus USD 0.35 for the runs. Form 4 adds volume: large companies file several insider forms a week, so budget for that if you include it.

### Limits and notes

- The SEC's submissions feed lists the latest 1,000 filings per company. The comparison uses that list, so a company would need more than 1,000 filings between two runs for anything to be missed.
- The actor stays under the SEC's 10 requests per second guidance and identifies itself with a contact address as the SEC requires. One request per company per run plus one for the ticker list.
- Tickers are resolved with the SEC's official ticker list. Delisted or very new tickers may not be in it; use the CIK instead. Unresolved entries are listed in `not_found` in the summary.
- If EDGAR is unreachable for a company, its previous snapshot is kept so nothing is missed on the next run.
- New filings usually appear in the submissions feed within a few minutes of acceptance. The feed is not a real-time stream; schedule frequency sets your delay.

# Actor input Schema

## `companies` (type: `array`):

Ticker symbols (AAPL) or CIK numbers (320193). One company per line.

## `formTypes` (type: `array`):

Only alert on these forms. Examples: 8-K, 10-K, 10-Q, 4, SC 13D, SC 13G, S-1, DEF 14A. You can write 13D/G as shorthand for both. Leave empty for every form type.

## `includeAmendments` (type: `boolean`):

Also alert on amended versions of the selected forms, e.g. 10-K/A when 10-K is selected.

## `items8K` (type: `array`):

Only alert on 8-K filings that include at least one of these item numbers, e.g. 5.02 (officer or director changes), 1.01 (material agreement), 2.02 (results), 8.01 (other events). Other form types are not affected.

## `keywords` (type: `array`):

Case-insensitive words matched against the form type, 8-K items and the primary document description. A filing is reported if any keyword matches.

## `initialLookbackDays` (type: `integer`):

On the very first run for a watchlist, also report filings dated within this many days. 0 means the first run only saves a baseline and reports nothing. Use 30 to see recent filings immediately.

## `watchlistName` (type: `string`):

Name for this watchlist. The actor keeps its last snapshot in a key-value store named sec-filing-alerts-<name>. If left empty, the name is derived from the list of companies, so changing the list starts a fresh baseline.

## `webhookUrl` (type: `string`):

HTTPS endpoint that receives one POST per run with the run summary and the list of alerts as JSON.

## `slackWebhookUrl` (type: `string`):

Slack incoming webhook. One message per run listing the new filings.

## `maxAlertsPerRun` (type: `integer`):

Cap on alert rows delivered (and charged) in one run. Extra filings are counted in the run summary but not delivered.

## Actor input object example

```json
{
  "companies": [
    "AAPL",
    "320193",
    "MSFT"
  ],
  "formTypes": [
    "8-K",
    "10-K",
    "10-Q",
    "4"
  ],
  "includeAmendments": true,
  "items8K": [],
  "keywords": [],
  "initialLookbackDays": 30,
  "watchlistName": "my-watchlist",
  "maxAlertsPerRun": 500
}
```

# Actor output Schema

## `alerts` (type: `string`):

Dataset rows, one per change

## `summary` (type: `string`):

Counts for this run

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "AAPL",
        "TSLA",
        "NVDA"
    ],
    "formTypes": [
        "8-K",
        "10-K",
        "10-Q",
        "4"
    ],
    "items8K": [],
    "keywords": [],
    "initialLookbackDays": 30,
    "watchlistName": "my-watchlist"
};

// Run the Actor and wait for it to finish
const run = await client.actor("skillmerc/sec-filing-alerts").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": [
        "AAPL",
        "TSLA",
        "NVDA",
    ],
    "formTypes": [
        "8-K",
        "10-K",
        "10-Q",
        "4",
    ],
    "items8K": [],
    "keywords": [],
    "initialLookbackDays": 30,
    "watchlistName": "my-watchlist",
}

# Run the Actor and wait for it to finish
run = client.actor("skillmerc/sec-filing-alerts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "AAPL",
    "TSLA",
    "NVDA"
  ],
  "formTypes": [
    "8-K",
    "10-K",
    "10-Q",
    "4"
  ],
  "items8K": [],
  "keywords": [],
  "initialLookbackDays": 30,
  "watchlistName": "my-watchlist"
}' |
apify call skillmerc/sec-filing-alerts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,skillmerc/sec-filing-alerts"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HTi2kYeyZfbR1EoyA/builds/hRI50chcAaeTJW4Q0/openapi.json
