/api/v1/form-13f/aggregation/by-industryIndustry-first ownership rollup with reporter-comparable flow, momentum, top movers, and parent-sector context.
Industry-first ownership rollup with reporter-comparable flow, momentum, top movers, and parent-sector context. Comparison coverage is returned on industry, parent-sector, and mover rows; unavailable activity remains null.
Why use this
Common use case
Industry-first view of current institutional ownership and reporter-comparable trading activity. Ownership values include every admitted current reporter. Flow, significance, momentum, previous-quarter flow changes, and mover rankings use only usable comparisons for managers reporting in both adjacent quarters. Each industry, nested parent sector, and top mover exposes comparison coverage. Default ranked results omit unavailable flow; sector-filtered and limit=all views keep unavailable rows after known values. The endpoint remains the flat counterpart to the sector-first rollup.
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 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 | Industry classification (e.g. `Semiconductors`, `Software - Application`, `Biotechnology`, `Banks - Diversified`). Use together with `sector.name` to disambiguate cross-sector industries (rare but possible in the taxonomy). |
| data.industries[].sector | object | no | Parent-sector context with current ownership, comparable flow, and comparison_position_count, comparison_unavailable_count, and comparison_status. Scalar fields can be null if the parent sector row is missing. |
| data.industries[].fund_flow | number | yes | Comparable net dollar flow for the industry. Null means unavailable; zero means measured no net flow. |
| data.industries[].comparison_position_count | integer | yes | Usable manager-security comparisons rolled into the industry. |
| data.industries[].comparison_unavailable_count | integer | yes | Unavailable manager-security comparisons rolled into the industry. |
| data.industries[].comparison_status | string | yes | complete, partial, unavailable, or null for legacy unknown coverage. |
| 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 | yes | Comparable fund flow divided by current total value. Null when flow is unavailable or total value is zero. |
| data.industries[].momentum_label | string | yes | Momentum label derived from comparable flow significance. Null when comparable activity is unavailable. |
| 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 five securities by absolute known comparable flow. Unavailable-flow rows are excluded; measured zero remains eligible. Each mover carries fund_count_comparable and comparison coverage. |
| data.industries[].compare | object | yes | Present for compare=prev. Flow and momentum changes are null if either quarter is unavailable; prev_comparison_status states prior coverage. |
| 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?quarter=2025-12-31&compare=prev&limit=20&sort_by=significance§or=Technology" \
-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).