Browse all documentation

Large holders API reference

Holders of more than 5% of a company, from Schedules 13D and 13G

Overview

Large holders are the people and firms that own more than 5% of a US company's shares. They report on Schedule 13D, for a holder that may seek control (tagged activist), and on Schedule 13G, for a passive holder (tagged passive), and on amendments to either. Every request needs a Bearer key, and REST and MCP draw on one credit balance.

Four routes cover the large holders of a company, the large stakes of one holder across companies, and two name searches that find a holder or a company to read. A company is addressed by its Filings API id, for example usa:0000320193. A holder is addressed by its CIK.

By default a route answers the current stakes: each holder's latest filing for each class of shares. A stake whose latest filing reports an exit, or that a later filing of the same filer group left out, is not listed. Send history=true to read every filing, newest first.

History starts with filings of October 2024. A holder's stakes page can hold fewer rows than limit and still end with a next_cursor, so keep reading until next_cursor is null. The US is the only country covered.

Base URL: https://api.narwhalapi.com. Each route below is an MCP tool of its own, with the same parameters.

Officers, directors and 10% owners are on the insider trades page.

Company ids are the ones the Filings API returns from company search.

What every account gets

WhatEvery account
Large holders, four routesIncluded

See pricing for what a call costs. A request is charged at the price of its API unless a route says otherwise.

  • Billed at the Companies price. Each successful answer is one call, whatever the number of rows, and an empty page is charged too. Errors are not charged. A search with no hits is charged too.
  • Numbers are decimal strings. A field with no value is left out, a list is always present, and a flag such as officer is sent only when true.
  • A joint filing has one row for each reporting person, and the rows share a filing_id. Each person states the same group figure on their own cover page, so never add shares across the people of one filing. Group the rows by filing_id and read the group's figure from group_total.
  • A figure a filing does not give, or that could not be read cleanly, is left out. Nothing is estimated.
  • A holder page reads at most 30 company files, so a holder in joint filings across hundreds of companies comes in short pages that end with a cursor.
  • A small number of filings we cannot read are left out of the answers. The CUSIP is not part of any answer.

Endpoints

Every route is a GET and needs your key in the Authorization: Bearer header. The examples show the shape of an answer, not live data.

List the large holders of a company

GET /v1/companies/{company_id}/beneficial-owners

Holders of more than 5% of a company's shares, from Schedules 13D and 13G and their amendments. By default each holder's current stake in each class; history lists every filing.

Dates narrow the filings before the latest one of each stake is chosen, so filed_lte gives the large holders of the company as they stood on that day.

MCP: tool filings_list_beneficial_owners.

Parameters

ParameterWhereRequiredTypeMeaning
company_idpathYesstringThe company id, for example usa:0000320193. A ticker alias such as usa:AAPL is accepted.
schedulequeryNoone of 13D, 13GOnly 13D (holders that may seek control) or 13G (passive holders).
typequeryNoone of activist, passiveactivist is the same as 13D and passive the same as 13G. When schedule is also sent, the two must agree.
historyqueryNobooleanfalse (the default) answers the current stakes. true lists every filing, newest first.
is_latestqueryNobooleanOnly with history=true. true keeps the latest filing of each stake and false keeps the earlier ones.
filedqueryNodateOnly filings made on this day.
filed_fromqueryNodateSame as filed_gte.
filed_toqueryNodateSame as filed_lte.
filed_gtqueryNodateOnly filings made after this day.
filed_gtequeryNodateOnly filings made on or after this day.
filed_ltqueryNodateOnly filings made before this day.
filed_ltequeryNodateOnly filings made on or before this day.
cursorqueryNostringnext_cursor of the previous page, with the same other parameters.
limitqueryNointegerRows per page. Default 50, at most 1000.

Response fields

FieldTypeSentMeaning
idstringAlwaysThe company id on the owners route, and the holder id on the stakes route.
companystringOptionalName of the company.
ownerslist of objectAlwaysThe large holders of the company, newest first.
owners[].filing_idstringAlwaysId of the filing the row comes from.
owners[].formone of 13D, 13D/A, 13G, 13G/AAlwaysThe schedule and whether it amends an earlier one: 13D, 13D/A, 13G or 13G/A.
owners[].fileddateAlwaysDay the filing was made.
owners[].accepteddate-timeOptionalThe moment the SEC accepted the filing.
owners[].event_datedateOptionalDate of the event that required the filing.
owners[].amendment_numberintegerOptionalNumber of the amendment, when the filing states it.
owners[].filer_idstringOptionalId of the first filer of the filing, the firm that submitted it.
owners[].filerstringOptionalName of the first filer. It can differ from the reporting person.
owners[].holder_idstringOptionalId of the reporting person. An individual has none.
owners[].holderstringAlwaysName of the reporting person.
owners[].holder_typestringOptionalCover page code of the person: IN individual, CO corporation, PN partnership, IA investment adviser, HC holding company, BK bank, and others.
owners[].citizenshipstringOptionalCitizenship or place of organization of the person.
owners[].class_titlestringOptionalTitle of the class of shares.
owners[].sharesstringOptionalShares the person reports owning. On a joint filing do not add these across people. Use group_total.
owners[].percent_of_classstringOptionalPercent of the class the person reports owning.
owners[].sole_voting_powerstringOptionalShares the person alone can vote.
owners[].shared_voting_powerstringOptionalShares the person shares the vote on.
owners[].sole_dispositive_powerstringOptionalShares the person alone can sell.
owners[].shared_dispositive_powerstringOptionalShares the person shares the power to sell.
owners[].group_boxone of a, b, abOptionalWhat the person ticked in cover row 2: a is a member of a group, b is not or does not affirm it, ab both.
owners[].rulestringOptionalThe rule a 13G was filed under: 13d-1(b), 13d-1(c) or 13d-1(d).
owners[].fundsstringOptionalA 13D's source of funds code, for example WC, AF, PF or OO.
owners[].typeone of activist, passiveOptionalactivist for Schedule 13D and passive for Schedule 13G.
owners[].legal_proceedingsalways trueOptionalTrue when the cover box for legal proceedings is ticked.
owners[].excludes_certain_sharesalways trueOptionalTrue when the cover box for excluding certain shares is ticked.
owners[].previously_filedalways trueOptionalTrue when the filing carries the previously filed flag.
owners[].issuer_addressstringOptionalAddress of the company, as filed.
owners[].purposestringOptionalA 13D's Item 4, the purpose of the transaction. Cut at 4,000 characters.
owners[].itemsobjectOptionalThe text of a 13D's items 1, 2, 3, 5 and 6, or a 13G's item 8, each cut at 4,000 characters. Only items the filing gives.
owners[].jointintegerOptionalHow many people the filing names.
owners[].repeatalways trueOptionalTrue when the person states a figure that an earlier person on the filing already stated.
owners[].group_totalstringOptionalOn a joint filing, the largest aggregate any of its people reports. Read the group's figure here.
owners[].is_latestbooleanAlwaysTrue on the latest filing of the stake among the filings the request keeps.
owners[].exitalways trueOptionalTrue when the filing reports the holder at 5% or less, or with no shares.
owners[].supersededalways trueOptionalTrue on the latest filing of a stake that a later filing of the same filer group no longer lists.
next_cursorstringAlwaysPass as cursor to read the next page. Always sent; null on the last page.
Request
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/companies/usa:0000320193/beneficial-owners?limit=1"
Example response
{
  "id": "usa:0000320193",
  "company": "Apple Inc.",
  "owners": [
    {
      "filing_id": "usa:0000320193:0002100119-26-000139",
      "form": "13G",
      "filed": "2026-04-29",
      "accepted": "2026-04-29T16:40:10Z",
      "event_date": "2026-03-31",
      "filer_id": "usa:0002100119",
      "filer": "VANGUARD CAPITAL MANAGEMENT LLC",
      "holder_id": "usa:0002100119",
      "holder": "Vanguard Capital Management",
      "holder_type": "IA",
      "citizenship": "PA",
      "class_title": "Common Stock",
      "shares": "1099168953",
      "percent_of_class": "7.48",
      "sole_voting_power": "145321305",
      "shared_voting_power": "0",
      "sole_dispositive_power": "1099168953",
      "shared_dispositive_power": "0",
      "rule": "13d-1(b)",
      "issuer_address": "1 Apple Park Way, Cupertino, CA, 95014",
      "is_latest": true
    }
  ],
  "next_cursor": null
}

List the large stakes of a holder

GET /v1/investors/{cik}/beneficial-ownership

What one holder owns across companies, from its Schedules 13D and 13G. By default the current stake in each class of each company; history lists every filing. A page can hold fewer rows than limit and still end with a next_cursor: keep reading until it is null.

cik is the holder's CIK. company_id and company on each row name the company the stake is in. ticker keeps the stakes in one company, and a ticker that matches no company is 404 company_not_found.

A page can be shorter than limit. Keep following next_cursor until it is null.

MCP: tool filings_list_investor_beneficial_ownership.

Parameters

ParameterWhereRequiredTypeMeaning
cikpathYesstringThe holder's CIK, one to ten digits.
schedulequeryNoone of 13D, 13GOnly 13D (holders that may seek control) or 13G (passive holders).
typequeryNoone of activist, passiveactivist is the same as 13D and passive the same as 13G. When schedule is also sent, the two must agree.
historyqueryNobooleanfalse (the default) answers the current stakes. true lists every filing, newest first.
is_latestqueryNobooleanOnly with history=true. true keeps the latest filing of each stake and false keeps the earlier ones.
filedqueryNodateOnly filings made on this day.
filed_fromqueryNodateSame as filed_gte.
filed_toqueryNodateSame as filed_lte.
filed_gtqueryNodateOnly filings made after this day.
filed_gtequeryNodateOnly filings made on or after this day.
filed_ltqueryNodateOnly filings made before this day.
filed_ltequeryNodateOnly filings made on or before this day.
cursorqueryNostringnext_cursor of the previous page, with the same other parameters.
limitqueryNointegerRows per page. Default 50, at most 1000.
tickerqueryNostringOnly stakes in the company with this ticker.

Response fields

FieldTypeSentMeaning
idstringAlwaysThe company id on the owners route, and the holder id on the stakes route.
holderstringOptionalName of the holder.
stakeslist of objectAlwaysThe stakes of the holder, newest first.
stakes[].filing_idstringAlwaysId of the filing the row comes from.
stakes[].formone of 13D, 13D/A, 13G, 13G/AAlwaysThe schedule and whether it amends an earlier one: 13D, 13D/A, 13G or 13G/A.
stakes[].fileddateAlwaysDay the filing was made.
stakes[].accepteddate-timeOptionalThe moment the SEC accepted the filing.
stakes[].event_datedateOptionalDate of the event that required the filing.
stakes[].amendment_numberintegerOptionalNumber of the amendment, when the filing states it.
stakes[].filer_idstringOptionalId of the first filer of the filing, the firm that submitted it.
stakes[].filerstringOptionalName of the first filer. It can differ from the reporting person.
stakes[].holder_idstringOptionalId of the reporting person. An individual has none.
stakes[].holderstringAlwaysName of the reporting person.
stakes[].holder_typestringOptionalCover page code of the person: IN individual, CO corporation, PN partnership, IA investment adviser, HC holding company, BK bank, and others.
stakes[].citizenshipstringOptionalCitizenship or place of organization of the person.
stakes[].class_titlestringOptionalTitle of the class of shares.
stakes[].sharesstringOptionalShares the person reports owning. On a joint filing do not add these across people. Use group_total.
stakes[].percent_of_classstringOptionalPercent of the class the person reports owning.
stakes[].sole_voting_powerstringOptionalShares the person alone can vote.
stakes[].shared_voting_powerstringOptionalShares the person shares the vote on.
stakes[].sole_dispositive_powerstringOptionalShares the person alone can sell.
stakes[].shared_dispositive_powerstringOptionalShares the person shares the power to sell.
stakes[].group_boxone of a, b, abOptionalWhat the person ticked in cover row 2: a is a member of a group, b is not or does not affirm it, ab both.
stakes[].rulestringOptionalThe rule a 13G was filed under: 13d-1(b), 13d-1(c) or 13d-1(d).
stakes[].fundsstringOptionalA 13D's source of funds code, for example WC, AF, PF or OO.
stakes[].typeone of activist, passiveOptionalactivist for Schedule 13D and passive for Schedule 13G.
stakes[].legal_proceedingsalways trueOptionalTrue when the cover box for legal proceedings is ticked.
stakes[].excludes_certain_sharesalways trueOptionalTrue when the cover box for excluding certain shares is ticked.
stakes[].previously_filedalways trueOptionalTrue when the filing carries the previously filed flag.
stakes[].issuer_addressstringOptionalAddress of the company, as filed.
stakes[].purposestringOptionalA 13D's Item 4, the purpose of the transaction. Cut at 4,000 characters.
stakes[].itemsobjectOptionalThe text of a 13D's items 1, 2, 3, 5 and 6, or a 13G's item 8, each cut at 4,000 characters. Only items the filing gives.
stakes[].jointintegerOptionalHow many people the filing names.
stakes[].repeatalways trueOptionalTrue when the person states a figure that an earlier person on the filing already stated.
stakes[].group_totalstringOptionalOn a joint filing, the largest aggregate any of its people reports. Read the group's figure here.
stakes[].is_latestbooleanAlwaysTrue on the latest filing of the stake among the filings the request keeps.
stakes[].exitalways trueOptionalTrue when the filing reports the holder at 5% or less, or with no shares.
stakes[].supersededalways trueOptionalTrue on the latest filing of a stake that a later filing of the same filer group no longer lists.
stakes[].company_idstringAlwaysId of the company the stake is in.
stakes[].companystringOptionalName of the company the stake is in.
next_cursorstringAlwaysPass as cursor to read the next page. Always sent; null on the last page.
Request
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/investors/0000102909/beneficial-ownership?filed_lte=2025-10-31&limit=1"
Example response
{
  "id": "usa:0000102909",
  "holder": "The Vanguard Group",
  "stakes": [
    {
      "filing_id": "usa:0001770450:0000102909-25-000347",
      "form": "13G/A",
      "filed": "2025-10-31",
      "accepted": "2025-10-31T11:42:47Z",
      "event_date": "2025-09-30",
      "amendment_number": 8,
      "filer_id": "usa:0000102909",
      "filer": "VANGUARD GROUP INC",
      "holder_id": "usa:0000102909",
      "holder": "The Vanguard Group",
      "holder_type": "IA",
      "citizenship": "PA",
      "class_title": "Common Stock",
      "shares": "10397351",
      "percent_of_class": "8.26",
      "sole_voting_power": "0",
      "shared_voting_power": "733054",
      "sole_dispositive_power": "9549123",
      "shared_dispositive_power": "848228",
      "rule": "13d-1(b)",
      "issuer_address": "201 Merritt 7, Norwalk, CT, 06851",
      "is_latest": true,
      "company_id": "usa:0001770450",
      "company": "Xerox Holdings Corp"
    }
  ],
  "next_cursor": "eyJrIjoiNzk3NDg5Njg3OTc0…"
}

Search large-holder filers by name

GET /v1/beneficial-ownership/filers

Find a holder that files Schedules 13D or 13G by the start of its name. Returns the id to use as cik on the stakes route.

Returns the id to pass as cik on the stakes route. The name needs at least two letters or digits besides words like Inc, or the answer is 400 invalid_name.

MCP: tool filings_search_beneficial_ownership_filers.

Parameters

ParameterWhereRequiredTypeMeaning
namequeryYesstringThe first letters of the name. At least two letters or digits.
countryqueryNostringThree-letter country code of the registry to search. Left out means USA. A country the route does not cover is 404 not_covered.
limitqueryNointegerHits to return. Default 20, at most 100.

Response fields

FieldTypeSentMeaning
filerslist of objectAlwaysThe filers whose name starts with the text.
filers[].idstringAlwaysThe filer's id, to pass as cik on the stakes route.
filers[].namestringAlwaysA name the filer used in a filing.
Request
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/beneficial-ownership/filers?name=vanguard&limit=3"
Example response
{
  "filers": [
    {
      "id": "usa:0002100119",
      "name": "VANGUARD CAPITAL MANAGEMENT LLC"
    },
    {
      "id": "usa:0001623658",
      "name": "Vanguard Charitable Endowment Program"
    },
    {
      "id": "usa:0002059874",
      "name": "Vanguard Development Holdings Limited"
    }
  ]
}

Search companies with large holders by name

GET /v1/beneficial-ownership/companies

Find a company that has Schedule 13D or 13G filings against it by the start of its name. Returns the id to use as company_id on the owners route.

Returns the id to pass as company_id on the owners route.

MCP: tool filings_search_beneficial_ownership_companies.

Parameters

ParameterWhereRequiredTypeMeaning
namequeryYesstringThe first letters of the name. At least two letters or digits.
countryqueryNostringThree-letter country code of the registry to search. Left out means USA. A country the route does not cover is 404 not_covered.
limitqueryNointegerHits to return. Default 20, at most 100.

Response fields

FieldTypeSentMeaning
companieslist of objectAlwaysThe companies whose name starts with the text.
companies[].idstringAlwaysThe company's id, to pass as company_id on the owners route.
companies[].namestringAlwaysName of the company.
Request
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/beneficial-ownership/companies?name=apple&limit=2"
Example response
{
  "companies": [
    {
      "id": "usa:0000320193",
      "name": "Apple Inc."
    },
    {
      "id": "usa:0001418121",
      "name": "Apple Hospitality REIT, Inc."
    }
  ]
}

Errors

Errors use the shared problem shape with a request_id. See Errors and credits for the shape and the credit headers. Failed requests are not charged.

CodeStatusMeaning
invalid_query400A parameter is missing, unknown, repeated or outside its range.
invalid_cursor400The cursor is not one this request returned, or it comes from a different request.
invalid_name400The name has fewer than two letters or digits once words like Inc are left out.
company_not_found404No company matches the id.
investor_not_found404No Schedule 13D or 13G filer matches the CIK.
not_covered404The market, country or company is not covered yet.
insufficient_credits402Your credit balance is less than the request costs.
company_data_unavailable503The filings behind this route cannot be read right now. Try again shortly.

Was this page helpful?