curl --request GET \
--url https://api.financialdatasets.ai/index-funds \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/index-funds"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.financialdatasets.ai/index-funds', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.financialdatasets.ai/index-funds",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.financialdatasets.ai/index-funds"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.financialdatasets.ai/index-funds")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/index-funds")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"ticker": "<string>",
"fund": {
"name": "<string>",
"cik": "<string>",
"asset_class": "<string>",
"as_of": "2023-12-25",
"filing_date": "2023-12-25",
"source": "<string>",
"total_net_assets": 123,
"total_holdings": 123,
"returned": 123,
"offset": 123
},
"holdings": [
{
"ticker": "<string>",
"name": "<string>",
"cusip": "<string>",
"isin": "<string>",
"weight": 123,
"market_value": 123,
"shares": 123,
"asset_class": "<string>"
}
],
"next_page_url": "<string>"
}{
"error": "Bad Request",
"message": "Invalid request parameters"
}{
"error": "Unauthorized",
"message": "Invalid API key provided"
}{
"error": "Payment Required",
"message": "This endpoint requires a paid subscription. Please upgrade your plan."
}{
"error": "Not Found",
"message": "Ticker XXXX not found"
}Holdings (by fund)
Get an ETF or index fund’s holdings and each position’s weight, sourced direct from SEC fund holdings filings.
curl --request GET \
--url https://api.financialdatasets.ai/index-funds \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/index-funds"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.financialdatasets.ai/index-funds', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.financialdatasets.ai/index-funds",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.financialdatasets.ai/index-funds"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.financialdatasets.ai/index-funds")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/index-funds")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"ticker": "<string>",
"fund": {
"name": "<string>",
"cik": "<string>",
"asset_class": "<string>",
"as_of": "2023-12-25",
"filing_date": "2023-12-25",
"source": "<string>",
"total_net_assets": 123,
"total_holdings": 123,
"returned": 123,
"offset": 123
},
"holdings": [
{
"ticker": "<string>",
"name": "<string>",
"cusip": "<string>",
"isin": "<string>",
"weight": 123,
"market_value": 123,
"shares": 123,
"asset_class": "<string>"
}
],
"next_page_url": "<string>"
}{
"error": "Bad Request",
"message": "Invalid request parameters"
}{
"error": "Unauthorized",
"message": "Invalid API key provided"
}{
"error": "Payment Required",
"message": "This endpoint requires a paid subscription. Please upgrade your plan."
}{
"error": "Not Found",
"message": "Ticker XXXX not found"
}Overview
Give us a fund ticker, get its full list of holdings and each position’s percent of net assets. Constituents are returned sorted by weight descending, with a fund header that carries the as-of period and coverage counts. Use this to answer “what’s in SPY, and at what weight?” for index replication, exposure analysis, and overlap checks. To get started, please create an account and grab your API key at financialdatasets.ai. You will use the API key to authenticate your API requests.Coverage
| Funds | Years of Coverage | Updated |
|---|---|---|
| 500+ | 5+ years | Daily |
The “latest” definition
Without anas_of filter, this endpoint returns the fund’s most recent filing. To reconstruct a historical composition, pass as_of=YYYY-MM-DD and the response is the composition in effect on or before that date.
All holdings, labeled
Every position is returned, including bonds, derivatives, and cash, each labeled with anasset_class (equity, bond, or other). Identifiers (cusip, isin, name) are included when available; ticker is null for securities without a US listing (e.g., many bonds and foreign holdings). To narrow the list, pass asset_class=equity or asset_class=bond.
Find available tickers
To discover which funds are available, hit the helper endpoint:import requests
# free endpoint, no API key required
url = 'https://api.financialdatasets.ai/index-funds/tickers/'
response = requests.get(url)
tickers = response.json().get('tickers')
print(f'{len(tickers)} funds available')
Filtering the Data
ticker is required. Optional filters:
as_of— the composition in effect on/before this date (YYYY-MM-DD). Defaults to the latest filing.asset_class—equityorbond. Defaults to all holdings.
limit is 50 (max 1000). Use offset to page through a fund’s constituents.
Examples
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'SPY' # fund ticker
limit = 50 # number of holdings to return
# create the URL
url = (
f'https://api.financialdatasets.ai/index-funds/'
f'?ticker={ticker}'
f'&limit={limit}'
)
# make API request
response = requests.get(url, headers=headers)
# parse holdings from the response
holdings = response.json().get('holdings')
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'SPY'
as_of = '2023-12-31' # composition in effect on/before this date
asset_class = 'equity' # equities only
# create the URL
url = (
f'https://api.financialdatasets.ai/index-funds/'
f'?ticker={ticker}'
f'&as_of={as_of}'
f'&asset_class={asset_class}'
)
# make API request
response = requests.get(url, headers=headers)
# parse holdings from the response
holdings = response.json().get('holdings')
Authorizations
API key for authentication.
Query Parameters
The fund's ticker symbol (e.g., SPY). Returns that fund's holdings. Mutually exclusive with holding.
A held security's ticker symbol (e.g., AAPL). Returns the funds whose latest filing holds it. Mutually exclusive with ticker.
Only valid with ticker. Returns the fund composition in effect on or before this date (YYYY-MM-DD). Without it, the fund's latest filing is returned.
Only valid with ticker. Filter constituents by instrument type: equity or bond. Omit for all holdings.
equity, bond The total number of rows to return (default: 50; no maximum). This is the total across all pages, not a page size: each page holds up to 10 records, linked by next_page_url.
The number of rows to skip, for pagination (default: 0).
Opaque pagination cursor from a previous response's next_page_url. When provided, all other query parameters are ignored: the cursor carries the original request's filters. Treat it as opaque; do not construct or modify it.
Response
Index fund holdings response. The shape depends on the query direction: ticker returns a fund header + constituents; holding returns a security header + funds.
- Option 1
- Option 2
Forward response (?ticker=...): a fund header plus its constituents, sorted by weight descending.
The fund ticker echoed back from the request.
Fund header: identity, the as-of period, and coverage counts for the full fund (not the returned page).
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Absolute URL of the next page of results. Present only when more results remain; request it as-is to continue. Each page holds up to 10 records.