Get started
Funds

ETF holdings API,
top positions and weights.

Fund profiles, the positions of each portfolio snapshot and reported allocations for U.S.-listed ETFs, with mutual funds on Commercial and Scale. Each holding links to its own listing when OHLC can resolve it, so a fund's top positions join directly to prices and fundamentals.

Fund profiles

Name, fund type, inception date, expense ratio, assets under management, NAV and benchmark, as reported.

Holdings snapshot

Most ETFs' every position, and the 10 largest of a mutual fund, by weight. meta.snapshot says how many are listed and what share of the fund they cover.

Allocations on six axes

dimension=sector, country, region, asset_class, market_cap or currency.

Mutual funds on Commercial and Scale

fund_type=mutual_fund profiles and portfolios need a Commercial or Scale plan.

Fund profiles

/v1/funds returns one profile per fund: name, fund_type (etf or mutual_fund), domicile, inception_date, benchmark_instrument_id, expense_ratio as a ratio (0.00095 is 0.095%), assets_under_management and net_asset_value as money objects, and the observed_on date of the figures. Fields a fund does not report are null. Look a fund up by symbol, then use its instrument_id for holdings and allocations:

From ticker to allocationscURL
# 1. Profile and stable ID for SPY
curl 'https://api.ohlc.io/v1/funds?symbols=ARCX:SPY' \
  -H "Authorization: Bearer $OHLC_API_KEY"

# 2. Sector weights from the latest snapshot
curl 'https://api.ohlc.io/v1/funds/01M35ZNRDCZSWM3GGGF5HDGJ80/allocations?dimension=sector' \
  -H "Authorization: Bearer $OHLC_API_KEY"

ETF holdings: the positions of one snapshot

/v1/funds/{instrument_id}/holdings returns the positions of one portfolio snapshot, and every page of the cursor stays on that snapshot, so a list never mixes two dates. The source lists most ETFs' every position, but only the largest positions of some ETFs and the 10 largest of a mutual fund. meta.snapshot states it on every response: positions is how many the snapshot lists and weight the share of the fund they add up to. SPY's 502 positions covered 99.8% of the fund on October 18, 2026; a weight well under 1 means the list is the largest positions only.

Each row has the position name, asset_type and weight. holding links to the listing when OHLC can resolve the position, on any market OHLC carries, and is null for cash, unlisted assets and positions it cannot match, which are kept rather than discarded; provider_symbol keeps the position's own code (2330.TW) either way. The source reports weights only, so quantity and market_value are always null. A fund that holds a commodity directly, such as a gold trust, lists no positions; its allocations describe it.

Because resolved holdings carry an instrument_id, you can feed a fund's positions straight into /v1/eod, /v1/quotes or financial statements without matching names. A request costs 50 credits whatever its limit; a page holds up to 500 positions, and meta.next_cursor continues a larger snapshot.

Allocations by sector, country and asset class

/v1/funds/{instrument_id}/allocations returns the fund's reported breakdown on one axis per row: dimension, category and weight. In SPY's snapshot of September 25, 2026, the Technology sector weight was about 0.398. These are the fund's reported allocations, not a recalculation from holdings. Omit dimension to get every axis the fund reports in one response, and expect an axis to be absent when the fund does not report it.

Use cases

  • Look-through exposure to the largest names a portfolio of ETFs holds, and to sectors through allocations.
  • Overlap between two funds' top positions before buying both.
  • Fund comparison tables on expense ratio, AUM and inception date.
  • The reverse question, which funds hold a given stock, is answered by ownership with holder_type=fund.

Snapshot dates, as_of and history

effective_date selects the latest snapshot on or before that date, and the response keeps the snapshot's real snapshot_date. as_of is the knowledge cutoff. OHLC takes a snapshot of each fund about once a month and keeps the newest three, so this is a view of the current portfolio and its last two months, not a multi-year archive; recording began in late September 2026. With two snapshots, request each with its own effective_date to see how a fund's top positions changed between them; positions are matched across snapshots by the holding's instrument_id.

Plans and credits

ETF profiles, holdings and allocations are included on Pro, Commercial and Scale. Mutual funds are on Commercial and Scale only. Profiles cost 50 credits per symbol (500 for a whole-market page); holdings and allocations cost 50 credits per request. See pricing.

Holdings of SPY

RequestcURL
curl 'https://api.ohlc.io/v1/funds/01M35ZNRDCZSWM3GGGF5HDGJ80/holdings?limit=2' \
  -H "Authorization: Bearer $OHLC_API_KEY"
Response · Illustrative sampleJSON
{
  "data": [
    {
      "id": "record_04e047031ed6448a4c4b",
      "fund_id": "01M35ZNRDCZSWM3GGGF5HDGJ80",
      "snapshot_date": "2026-09-25",
      "holding": { "instrument_id": "01M35XSMSHNB6A3D7QN9CX96CE", "symbol": "XNAS:TSLA", "name": "Tesla Inc" },
      "name": "Tesla Inc",
      "asset_type": "equity",
      "quantity": null,
      "market_value": null,
      "weight": "0.0157742"
    },
    {
      "id": "record_07b7417ed57f30f5e1f6",
      "fund_id": "01M35ZNRDCZSWM3GGGF5HDGJ80",
      "snapshot_date": "2026-09-25",
      "holding": { "instrument_id": "01M35XR4MTFGABCSE4PDSZERTX", "symbol": "XNAS:AVGO", "name": "Broadcom Inc" },
      "name": "Broadcom Inc",
      "asset_type": "equity",
      "quantity": null,
      "market_value": null,
      "weight": "0.0257353"
    }
  ],
  "meta": {
    "timezone": "UTC",
    "as_of": "2026-10-03T15:04:46Z",
    "next_cursor": "AQCEYPcPqv9v...",
    "coverage": { "status": "partial", "reason": "Coverage is partial for the entitled query scope." },
    "snapshot": { "snapshot_date": "2026-09-25", "positions": 50, "weight": "0.6399474" }
  }
}

Prices delayed 15 minutes · Illustrative sample data

Questions, answered.

How do I get ETF holdings with an API?

Find the fund's instrument_id with GET /v1/funds?symbols=ARCX:SPY, then call GET /v1/funds/{instrument_id}/holdings. It returns the fund's positions, and meta.snapshot says how many and what share of the fund they cover.

Which ETFs hold a particular stock?

Use GET /v1/ownership?symbols=XNAS:NVDA&holder_type=fund, which lists fund holders of a stock with their reported positions.

Are mutual funds included?

Yes, on Commercial and Scale. Pro covers ETFs.

Why don't the holding weights add up to 100%?

Some funds list only their largest positions: meta.snapshot.weight is the share they cover (a mutual fund's 10 largest, for example). Leveraged and derivative-based portfolios also report weights that need not sum to one.

How often are ETF holdings updated?

About once a month per fund, and the newest three snapshots are kept. Every response states its snapshot_date, so check it rather than assuming a daily update.

A little JSON.
A lot of possibility.

Explore the API