Skip to content
/api/v1/form-13f/aggregation/basket-holdings

Aggregate a basket of fund CIKs into one per-CUSIP consensus view for a quarter.

Aggregate a basket of fund CIKs into one per-CUSIP consensus view for a quarter.

Why use this

One server-side GROUP BY across up to 20 funds' latest 13F holdings — returns one compact row per security (how many of the basket's funds hold it, summed value, summed shares, % of basket) instead of every holding of every fund. Optional compare_period adds quarter-over-quarter change (New / Increased / Decreased / Unchanged / Closed).

Common use case

Powering a 'smart-money consensus' basket report: pick 5-20 funds (e.g. Berkshire + Scion + Pershing Square + Appaloosa + Bridgewater), see which stocks the most managers agree on and how the basket shifted last quarter, in one request.

Replaces the legacy 'pull every holding of every fund into the client, then aggregate' basket flow (which could move 300K+ rows / multiple MB for mega-fund baskets) with ONE indexed server-side aggregation. For each requested CIK it selects the single latest-filed 13F-HR/A for period, applies the same holdings selection as GET /api/v1/form-13f/fund/{cik} (long-equity only, options excluded, transition-CUSIP dedup), then GROUPs BY CUSIP across the basket — so a basket's per-position and total values equal the SUM of the individual /fund reports.

funds_holding is COUNT(DISTINCT cik) — the consensus signal (how many of the basket's managers hold a name). Funds with no 13F for the period appear in basket.pending (not silently dropped). Pass compare_period for quarter-over-quarter change classification (New / Increased / Decreased / Unchanged / Closed) plus value/share deltas, keyed on canonical CUSIP so a corporate-action CUSIP change is not a phantom New/Closed. Max 20 CIKs per request. All monetary amounts USD (post-Plan-51 thousands-vs-actual normalization); share counts as-filed (not split-adjusted). Always-live — no caching.

Parameters

NameInRequiredDefaultAllowedDescriptionExample
ciksqueryrequiredComma-separated CIKs, 1-20. Zero-padded or bare both accepted.0001067983,0001649339,0001336528
periodqueryrequiredQuarter-end YYYY-MM-DD. Holdings come from each fund's latest 13F-HR/A filed for this period.2026-03-31
compare_periodqueryoptionalPrior quarter-end YYYY-MM-DD. When set, each position gains change_type + prev/delta fields, and Closed positions are synthesized.2025-12-31
sort_byqueryoptionalvaluevalue | shares | funds_holding | pct | name | ticker.
sort_orderqueryoptionaldescasc | desc.
sizequeryoptionalallPositions per page; default returns all positions (client paginates). Aliases: limit / from / offset.50

Response schema

FieldTypeNullableDescription
periodstringnoISO YYYY-MM-DD quarter-end echoed from the request.
compare_periodstringyesPrior quarter used for change classification, or null when not requested.
generated_atstringnoUTC timestamp the aggregation was computed (drives an 'as of' label; always-live, never cached).
basketobjectno{ total_funds, funds_filed, funds_pending, filed:[{cik,company_name}], pending:[{cik}] } — which requested funds actually filed for this period.
totalsobjectno{ total_value_usd, total_positions } — basket-wide long-equity value (post-Plan-51 normalization) and count of unique CUSIPs.
positionsarraynoOne row per CUSIP: { cusip, ticker, name_of_issuer, funds_holding (COUNT DISTINCT funds), value_usd, shares, pct_of_basket }. With compare_period: also change_type, prev_value_usd, value_change_pct, share_change. Long-equity only (options excluded), matching the per-fund /fund report.

Sample response

·
  • "period": "2026-03-31"
  • "compare_period": "2025-12-31"
  • "generated_at": "2026-06-28T16:03:07Z"
  • "basket":
    • "total_funds": 5
    • "funds_filed": 5
    • "funds_pending": 0
    • "filed":
    • "pending": []
    }
  • "totals":
    • "total_value_usd": 412600000000
    • "total_positions": 142
    }
  • "positions":
    ]
}

Errors

StatusLabelDescription
200OKRequest succeeded.
400Bad RequestInvalid query, body, or path parameter.
401UnauthorizedMissing or invalid Authorization header / api_Token.
402Payment RequiredInsufficient token balance for this call. Top up
429Too Many RequestsRate limit exceeded for your tier (see /pricing for tier limits). Tier limits
500Server ErrorUnexpected server-side failure. Retry with backoff; report if persistent.

Code samples

curl "https://api.finradar.ai/api/v1/form-13f/aggregation/basket-holdings" \
  -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).