/api/v1/form-13f/aggregation/by-industryIndustry-first mirror of /aggregation/by-sector — returns a flat industries array with sector context nested per industry.
Industry-first mirror of /aggregation/by-sector — returns a flat industries array with sector context nested per industry. Useful for cross-sector industry leaderboards (e.g. 'biggest inflow industries this quarter regardless of sector'). Same enrichment columns (fund_flow, total_value, unique_fund_count, flow_significance_pct, momentum_label, ETF value, position-change counts) and same top_movers semantics as the sector endpoint. Response includes quarter_metadata.
Why use this
Common use case
Industry-first cut of the institutional fund-flow analytics that power FinRadar's sector-rotation surfaces. Backed by the same sec_13f_sector_summary materialized view as GET /api/v1/form-13f/aggregation/by-sector (refreshed ~6h post-filing) — the row shape, top-movers resolution chain, and coverage_pct math are byte-identical to that endpoint. The difference is the top-level entity: industries are flattened into a single sorted list with sector context attached per row, instead of grouped under their parent sector.
Use this endpoint when the question is industry-first ('which industries had the biggest fund inflows this quarter regardless of sector?') instead of sector-first ('which sectors are rotating, and what industries are driving them?'). The flat-list shape lets you sort and slice across the full ~150-industry universe in one round-trip; the nested sector context per row keeps each result self-contained for leaderboard rendering. Pair with GET /api/v1/form-13f/aggregation/by-sector for full sector → industry → ticker drill-down hierarchies, and with GET /api/v1/form-13f/aggregation/by-ticker for per-CUSIP detail within a hot industry.
Use ?compare=prev to surface QoQ momentum shifts (e.g. 'Moderate Buying -> Strong Buying') — particularly useful for detecting industries breaking out of a neutral regime. Pass ?sector=Technology for a single-sector drill-down (skips the inflow/outflow split). All monetary values are in USD (post-Plan-51 thousands correction); share counts are NOT split-adjusted.
Parameters
| Name | In | Required | Default | Allowed | Description | Example |
|---|---|---|---|---|---|---|
| quarter | query | optional | — | — | Report period as `YYYY-MM-DD` (any quarter-end date). Defaults to the latest quarter present in `sec_13f_sector_summary`. | 2025-12-31 |
| compare | query | optional | — | — | Set to `prev` to include per-industry quarter-over-quarter deltas: `flow_change`, `prev_momentum_label`, `momentum_shift`, `fund_count_change`, `value_change_pct`. Omitted/any-other-value → `compare` is `null` per row. | prev |
| limit | query | optional | 50 | — | Top-N inflows AND Top-N outflows to return when no `sector` filter is set (so the response carries up to `2 × limit` industries). When `sector` is set, the inflow/outflow split is skipped and `limit` caps total industries returned. Integer (1-200) or the string `all` (returns the full industry universe — ~150 rows). Default 50. | 20 |
| sort_by | query | optional | fund_flow | — | `fund_flow` (absolute USD net flow) or `significance` (`flow_significance_pct = fund_flow / total_value × 100`). Inflows sort descending; outflows sort ascending by signed value (most negative first). With `sector` filter, all industries sort by `abs(metric)` descending. Legacy alias `sort` is accepted for cross-endpoint consistency with `/by-sector`. | significance |
| sector | query | optional | — | — | Optional drill-down. When set, restricts the response to industries within this sector and skips the inflow/outflow split (returns a single ranked list). Sector name must match the canonical Sharadar label exactly (e.g. `Technology`, `Healthcare`, `Financial Services`). | Technology |
Response schema
| Field | Type | Nullable | Description |
|---|---|---|---|
| status | string | no | `success` on a 2xx response, `error` otherwise. Standard `ApiResponse` envelope — `data` carries the payload. |
| data.quarter | string | no | ISO `YYYY-MM-DD` reporting quarter end. Echoed from the request; defaults to the latest available quarter in `sec_13f_sector_summary`. |
| data.total_institutional_value | number | no | Sum of `total_value` across ALL sectors this quarter (computed from the sector-level rows, NOT industry-level — same source as `/by-sector`). USD, post-Plan-51 thousands correction. Used to derive `coverage_pct`. |
| data.coverage_pct | number | no | Percentage of `total_institutional_value` that resolves to a classified sector (i.e. NOT `Unclassified`). Identical math to `/by-sector` so the two endpoints report the same number for the same quarter. Use as a data-quality gate before surfacing industry signals. |
| data.total_industries | integer | no | Number of industry rows returned BEFORE the inflow/outflow `limit` cap. When `sector` is set, counts industries within that sector only; otherwise counts the full industry universe for the quarter (typically ~150). |
| data.sector_filter | string | yes | Echoes back the `sector` query param when set; `null` when no filter was applied. Use to render an active-filter chip client-side. |
| data.industries | array | no | Flat industry array. When no `sector` filter: top-`limit` inflows followed by top-`limit` outflows (capped naturally by `total_industries`). When `sector` is set: industries within that sector sorted by `abs(sort_by metric)` descending, capped at `limit`. Each row carries its parent sector's context nested under `sector` for self-contained rendering. |
| data.industries[].industry | string | no | Sharadar industry classification (e.g. `Semiconductors`, `Software - Application`, `Biotechnology`, `Banks - Diversified`). Use together with `sector.name` to disambiguate cross-sector industries (rare but possible in Sharadar's taxonomy). |
| data.industries[].sector | object | no | Parent-sector context block: `{ name, fund_flow, total_value, unique_fund_count, flow_significance_pct, momentum_label, low_confidence }`. Values are the same the same sector would show on `/by-sector` — replicated here so industry leaderboard rows are self-contained without a second round-trip. Inner fields may be `null` if the sector row is missing (data-quality edge case). |
| data.industries[].fund_flow | number | no | Net dollar flow into the industry this quarter, in USD (post-Plan-51 thousands correction). Positive = net institutional buying; negative = net selling. The headline industry-rotation metric. |
| data.industries[].total_value | number | no | Total institutional position value in this industry this quarter, in USD. Sum of `value_usd` across all funds holding any CUSIP classified to this industry. |
| data.industries[].cusip_count | integer | no | Number of distinct CUSIPs classified to this industry this quarter. Indicates the depth of the industry's investable universe (Semiconductors ~90; Tobacco ~5). |
| data.industries[].unique_fund_count | integer | no | Number of distinct funds with at least one position in this industry. High `unique_fund_count` + high `fund_flow` = broad institutional consensus on the industry. |
| data.industries[].total_positions | integer | no | Total position rows (fund × CUSIP combinations) in this industry this quarter. Always ≥ `unique_fund_count × 1`; typically ~10× higher in deep industries like Semiconductors. |
| data.industries[].flow_significance_pct | number | no | `fund_flow / total_value × 100` — measures flow magnitude relative to industry size. Drives the `momentum_label` classification. |
| data.industries[].momentum_label | string | no | 5-tier momentum label derived from `flow_significance_pct`: `Strong Buying` (≥10%), `Moderate Buying` (≥3%), `Neutral` (-3 to +3%), `Moderate Selling` (≤-3%), `Strong Selling` (≤-10%). Same taxonomy as `/by-sector.momentum`. |
| data.industries[].low_confidence | boolean | no | `true` when industry coverage is sparse (low fund count or low CUSIP count) — surface in UI as a quality indicator and consider filtering out for actionable leaderboards. |
| data.industries[].etf_value | number | no | Sub-aggregate of `total_value` that comes from ETF positions (`security_group=ETFs`). Useful for distinguishing active industry bets (high non-ETF value) from passive sector-tilt exposure. |
| data.industries[].new_buys_count | integer | no | Number of (fund, CUSIP) pairs where the fund initiated a NEW position in this industry this quarter (no prior-quarter row). High new-buys count = multiple funds independently entering the industry — conviction signal. |
| data.industries[].closed_count | integer | no | Number of (fund, CUSIP) pairs the fund fully EXITED in this industry this quarter. Companion to `new_buys_count` for net-flow attribution. |
| data.industries[].increased_count | integer | no | Number of (fund, CUSIP) pairs where the fund ADDED to an existing position in this industry. |
| data.industries[].decreased_count | integer | no | Number of (fund, CUSIP) pairs where the fund TRIMMED an existing position in this industry. |
| data.industries[].top_movers | array | no | Top-5 CUSIPs by `abs(fund_flow)` within this industry — `[{ ticker, name, fund_flow, fund_count }, ...]`. Mirrors `/by-sector`'s per-industry top_movers list (same 2-level sector resolution chain: `cusip_mappings.sector` → `cusip_mappings.ticker → all_stocks_list`). CUSIPs resolved via fallback chains (≤5% of total holdings value) are not represented — by design, to keep the query fast. |
| data.industries[].compare | object | yes | QoQ comparison block — present and populated only when `?compare=prev`. Shape: `{ prev_quarter, flow_change, prev_momentum_label, momentum_shift, fund_count_change, value_change_pct }`. `momentum_shift` is a string like `'Moderate Buying -> Strong Buying'` (or `null` when momentum didn't change tier). When the industry didn't exist in the prior quarter, scalar fields are `null` but `prev_quarter` echoes the resolved date. |
| data.quarter_metadata | object | no | Filing-completeness state for the quarter: `{ quarter, filing_deadline, is_complete, days_until_deadline }`. Same shape as [GET /api/v1/form-13f/filing-progress](/docs/institutional-holdings/filing-progress-tracking/get-form-13f-filing-progress). `is_complete=false` during the 45-day post-quarter window — gate downstream industry-rotation analysis until the quarter has matured. |
Sample response
- "status": "success"
- "data":
- "quarter": "2025-12-31"
- "total_institutional_value": 22500000000000
- "coverage_pct": 99.5
- "total_industries": 158
- "sector_filter": null
- "industries":
- "quarter_metadata":
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/api/v1/form-13f/aggregation/by-industry" \
-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).