/insider-module/api/insiders/clustersDetect cluster buying/selling.
Detect cluster buying/selling. A cluster is a ONE-WEEK chain of same-direction trades (v3.145.0): each trade within one calendar week of the previous one. Each cluster includes sector/industry classification.
Why use this
Common use case
Detects coordinated cluster buying or selling — events where multiple distinct insiders trade the same ticker within a configurable window. Cluster definition: ≥min_insiders unique insiders trading the same ticker within the last days days, with aggregate value ≥min_value. Each cluster carries sector/industry classification and the v3.1.1 fix that counts unique transactions (not distinct owner entities) so multiple ownership vehicles of the same beneficial owner do not inflate the cluster size. Pair with GET /insider-module/api/insiders/recommendations/daily for productized buy/sell signals built on top of cluster detection.
Parameters
| Name | In | Required | Default | Allowed | Description | Example |
|---|---|---|---|---|---|---|
| filed_at_days | query | optional | 7 | — | SEARCH window by filing date (1-3650, days back from today): how far back to look for clusters. Does NOT define a cluster — clusters are always one-week chains regardless of this value; a wider window only returns more of them (possibly several per ticker+direction). `30` covers a month of detections, `90` a quarter. | 30 |
| transaction_days | query | optional | — | — | SEARCH window by trade-execution date (1-365). Bounds the scan only; never merges trades into one cluster. Omit to bound by filing date alone. | 30 |
| days | query | optional | — | — | DEPRECATED alias (1-90): sets BOTH `filed_at_days` and `transaction_days` to the same value and overrides them when present. Use the two explicit search-window params instead. | 30 |
| min_insiders | query | optional | 3 | — | Minimum number of distinct insiders that must trade for a ticker to qualify as a cluster. `2` is permissive (catches CEO+CFO pairs); `3` (default) matches academic literature; `5+` is for very high-conviction screens. Counts UNIQUE BENEFICIAL OWNERS (post-v3.1.1 fix) — multiple LLC vehicles of the same owner count as one. | 3 |
| min_value | query | optional | — | — | Minimum aggregate USD value (`SUM(shares × price)`) across all transactions in the cluster. Use to filter out small option-exercise clusters. `1000000` (1MM) eliminates most noise; `10000000` (10MM) typically returns only material conviction events. Omit (or `0`) to include all clusters meeting the insider-count threshold. | 1000000 |
| sector | query | optional | — | — | Sector filter, case-sensitive (e.g. `Technology`, `Healthcare`, `Energy`). Restricts the cluster scan to one sector — useful for sector-rotation thesis confirmation. Tickers without a sector mapping are excluded when this filter is set. | Technology |
| industry | query | optional | — | — | Industry filter, case-sensitive (more specific than `sector`). Em-dash characters require URL-encoding. Most useful for niche thematic screens (e.g. all clusters in `Biotechnology` or `Semiconductors`). | Consumer Electronics |
| exclude_cashless | query | optional | true | — | Exclude cashless option-exercise sells before aggregation. **Default `true` as of v3.78.0** (was `false`) so mechanical exercise sells don't form false SELL clusters. Pass `false` to include them. | false |
| exclude_10b5_1 | query | optional | true | — | Exclude pre-planned Rule 10b5-1 trades before aggregation. **Default `true` as of v3.78.0** (was `false`) — scheduled trades are not discretionary cluster signal. Pass `false` to include them. | false |
| exclude_sell_to_cover | query | optional | true | — | Exclude RSU sell-to-cover (tax-withholding) sales before aggregation. Default `true`. Pass `false` to include mandatory vest-day tax sells. | false |
Response schema
| Field | Type | Nullable | Description |
|---|---|---|---|
| [] | array | no | Bare JSON array (NOT wrapped in a `data`/`status`/`meta` envelope) of detected cluster rows — one row per ONE-WEEK CHAIN (v3.145.0) that meets the `min_insiders` + `min_value` thresholds. Sorted by aggregate value DESC. A single ticker can appear multiple times: once per direction AND once per distinct week-chain the search window reaches (e.g. a pair that traded in early July and again in late July is two rows). Empty array when no qualifying clusters detected. |
| [].ticker | string | yes | Issuer ticker exhibiting cluster activity (canonical hyphen form). The natural primary key together with `cluster_type`. |
| [].company_name | string | no | Issuer name (from CompanyStub). |
| [].sector | string | yes | Sector classification for the issuer (e.g. `Technology`, `Healthcare`). Null when the ticker is unmapped. Useful for cluster-by-sector roll-ups (e.g. 'Healthcare had 12 buy clusters this week vs. 2 sell'). |
| [].industry | string | yes | Industry classification (more specific than `sector`). Null when unmapped. Em-dash characters preserved verbatim. |
| [].issuer_cik | string | yes | Issuer CIK for the clustered company. |
| [].insider_count | integer | no | Distinct UNIQUE BENEFICIAL OWNERS in the cluster (post-v3.1.1 fix — multiple LLC/trust vehicles of the same person count as one). Always ≥`min_insiders`. The signal-density metric — values of 4-5 in a `days=30` window with no overlapping 10b5-1 plans is the strongest cluster signal. |
| [].total_value | string | no | Decimal value serialized as a JSON string. Aggregate USD value (`SUM(shares × price_per_share)`) across all transactions in the cluster. Excludes transactions with null `price_per_share` (grants, gifts). Always ≥`min_value` parameter. Use the per-cluster `total_value` ÷ ticker market cap to gauge signal materiality (whale clusters are 0.01-0.1% of mcap; routine 10b5-1 noise is < 0.01%). |
| [].net_shares | string | no | Decimal value serialized as a JSON string. Net COMMON SHARES for the cluster — positive for BUY clusters, negative for SELL clusters (the sign encodes direction). Counts Form 4 Table I rows only: a Table II quantity is a count of derivative securities (option/warrant/RSU contracts), not shares, so it is excluded rather than added into a share total. This is deliberately narrower than the cluster's transaction scope — an open-market warrant or option trade still contributes to `total_value` and `transaction_count`, it simply contributes no shares. As-filed counts, NOT split-adjusted. |
| [].transaction_count | integer | no | Total Form 4 transaction rows aggregated into the cluster. Always ≥`insider_count` (each insider contributes ≥1 transaction). High `transaction_count` per `insider_count` ratios (e.g. 10:3) indicate either a multi-day staggered buy program or 10b5-1 grid execution — inspect individual transaction dates before alerting. |
| [].first_date | string | no | ISO `YYYY-MM-DD` of the EARLIEST transaction in the cluster window. Together with `last_date` defines the cluster's time-coincidence span — narrower spans (1-3 days) indicate higher-conviction coordinated decisions; wider spans (15-30 days) may reflect rolling executions on a pre-set plan. |
| [].last_date | string | no | ISO `YYYY-MM-DD` of the LATEST transaction in the cluster window. The closer this is to today, the more actionable the signal — clusters with `last_date` within the last 5 trading days are the typical alert target. |
| [].insiders | array | no | Participant list: array of insider NAME strings (`List[str]`, NOT objects). Length equals `insider_count`. Use to render 'who bought' tooltips in cluster-detection dashboards. |
| [].cluster_type | string | no | Cluster direction — literal string `BUY` (cluster of acquisitions) or `SELL` (cluster of dispositions). BUY clusters are typically the higher-signal direction; SELL clusters can include high-noise routine 10b5-1 plan executions and tax-withholding sales (code F). |
| [].has_officer | boolean | no | `true` when the cluster INCLUDES ≥1 member who is a current officer at this issuer. A cluster-level 'includes a rank' flag (bool_or over members' current roles) — filter on it client-side to alert only on clusters that contain a given rank, rather than pre-filtering the aggregation to that rank. Since v3.78.0. |
| [].has_director | boolean | no | `true` when the cluster INCLUDES ≥1 member who is a current director at this issuer. Since v3.78.0. |
| [].has_c_suite | boolean | no | `true` when the cluster INCLUDES ≥1 member whose standardized officer title is C-suite. Under-reports when an officer's title was never standardized (`officer_title_id` unresolved), so treat `false` as 'not-known-C-suite', not authoritative. Since v3.78.0. |
| [].has_ten_percent_owner | boolean | no | `true` when the cluster INCLUDES ≥1 member who is a current 10%+ owner at this issuer. Since v3.78.0. |
Sample response
- "ticker": "AAPL"
- "company_name": "APPLE INC"
- "sector": "Technology"
- "industry": "Consumer Electronics"
- "issuer_cik": "0000320193"
- "insider_count": 4
- "total_value": "1240000"
- "net_shares": "7100"
- "transaction_count": 7
- "first_date": "2026-04-09"
- "last_date": "2026-04-15"
- "insiders":
- "cluster_type": "BUY"
- "has_officer": true
- "has_director": true
- "has_c_suite": true
- "has_ten_percent_owner": false
Errors
| Status | Label | Description |
|---|---|---|
| 200 | OK | Request succeeded. |
| 400 | Bad Request | Invalid query, body, or path parameter. |
| 401 | Unauthorized | Missing or invalid Authorization header / api_Token. |
| 402 | Payment Required | Insufficient token balance for this call. Top up |
| 429 | Too Many Requests | Rate limit exceeded for your tier (see /pricing for tier limits). Tier limits |
| 500 | Server Error | Unexpected server-side failure. Retry with backoff; report if persistent. |
Code samples
curl "https://api.finradar.ai/insider-module/api/insiders/clusters?api_Token=YOUR_API_KEY&filed_at_days=30&transaction_days=30&days=30&min_insiders=3&min_value=1000000§or=Technology&industry=Consumer+Electronics&exclude_cashless=false&exclude_10b5_1=false&exclude_sell_to_cover=false" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Generate an API key in /account/credentials to run live queries (literal YOUR_API_KEY placeholder shown until then).