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_, so keep reading until next_ is null. The US is the only country covered.
Base URL: https:/. 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
| What | Every account |
|---|---|
| Large holders, four routes | Included |
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
officeris sent only when true. - A joint filing has one row for each reporting person, and the rows share a
filing_. Each person states the same group figure on their own cover page, so never addid sharesacross the people of one filing. Group the rows byfiling_and read the group's figure fromid 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_ gives the large holders of the company as they stood on that day.
MCP: tool filings_.
Parameters
| Parameter | Where | Required | Type | Meaning |
|---|---|---|---|---|
company_ | path | Yes | string | The company id, for example usa:0000320193. A ticker alias such as usa:AAPL is accepted. |
schedule | query | No | one of 13D, 13G | Only 13D (holders that may seek control) or 13G (passive holders). |
type | query | No | one of activist, passive | activist is the same as 13D and passive the same as 13G. When schedule is also sent, the two must agree. |
history | query | No | boolean | false (the default) answers the current stakes. true lists every filing, newest first. |
is_ | query | No | boolean | Only with history=true. true keeps the latest filing of each stake and false keeps the earlier ones. |
filed | query | No | date | Only filings made on this day. |
filed_ | query | No | date | Same as filed_. |
filed_ | query | No | date | Same as filed_. |
filed_ | query | No | date | Only filings made after this day. |
filed_ | query | No | date | Only filings made on or after this day. |
filed_ | query | No | date | Only filings made before this day. |
filed_ | query | No | date | Only filings made on or before this day. |
cursor | query | No | string | next_ of the previous page, with the same other parameters. |
limit | query | No | integer | Rows per page. Default 50, at most 1000. |
Response fields
| Field | Type | Sent | Meaning |
|---|---|---|---|
id | string | Always | The company id on the owners route, and the holder id on the stakes route. |
company | string | Optional | Name of the company. |
owners | list of object | Always | The large holders of the company, newest first. |
owners[].filing_ | string | Always | Id of the filing the row comes from. |
owners[].form | one of 13D, 13D/A, 13G, 13G/A | Always | The schedule and whether it amends an earlier one: 13D, 13D/, 13G or 13G/. |
owners[].filed | date | Always | Day the filing was made. |
owners[].accepted | date-time | Optional | The moment the SEC accepted the filing. |
owners[].event_ | date | Optional | Date of the event that required the filing. |
owners[].amendment_ | integer | Optional | Number of the amendment, when the filing states it. |
owners[].filer_ | string | Optional | Id of the first filer of the filing, the firm that submitted it. |
owners[].filer | string | Optional | Name of the first filer. It can differ from the reporting person. |
owners[].holder_ | string | Optional | Id of the reporting person. An individual has none. |
owners[].holder | string | Always | Name of the reporting person. |
owners[].holder_ | string | Optional | Cover page code of the person: IN individual, CO corporation, PN partnership, IA investment adviser, HC holding company, BK bank, and others. |
owners[].citizenship | string | Optional | Citizenship or place of organization of the person. |
owners[].class_ | string | Optional | Title of the class of shares. |
owners[].shares | string | Optional | Shares the person reports owning. On a joint filing do not add these across people. Use group_. |
owners[].percent_ | string | Optional | Percent of the class the person reports owning. |
owners[].sole_ | string | Optional | Shares the person alone can vote. |
owners[].shared_ | string | Optional | Shares the person shares the vote on. |
owners[].sole_ | string | Optional | Shares the person alone can sell. |
owners[].shared_ | string | Optional | Shares the person shares the power to sell. |
owners[].group_ | one of a, b, ab | Optional | What 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[].rule | string | Optional | The rule a 13G was filed under: 13d-1(b), 13d-1(c) or 13d-1(d). |
owners[].funds | string | Optional | A 13D's source of funds code, for example WC, AF, PF or OO. |
owners[].type | one of activist, passive | Optional | activist for Schedule 13D and passive for Schedule 13G. |
owners[].legal_ | always true | Optional | True when the cover box for legal proceedings is ticked. |
owners[].excludes_ | always true | Optional | True when the cover box for excluding certain shares is ticked. |
owners[].previously_ | always true | Optional | True when the filing carries the previously filed flag. |
owners[].issuer_ | string | Optional | Address of the company, as filed. |
owners[].purpose | string | Optional | A 13D's Item 4, the purpose of the transaction. Cut at 4,000 characters. |
owners[].items | object | Optional | The 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[].joint | integer | Optional | How many people the filing names. |
owners[].repeat | always true | Optional | True when the person states a figure that an earlier person on the filing already stated. |
owners[].group_ | string | Optional | On a joint filing, the largest aggregate any of its people reports. Read the group's figure here. |
owners[].is_ | boolean | Always | True on the latest filing of the stake among the filings the request keeps. |
owners[].exit | always true | Optional | True when the filing reports the holder at 5% or less, or with no shares. |
owners[].superseded | always true | Optional | True on the latest filing of a stake that a later filing of the same filer group no longer lists. |
next_ | string | Always | Pass as cursor to read the next page. Always sent; null on the last page. |
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/companies/usa:0000320193/beneficial-owners?limit=1"{
"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_: keep reading until it is null.
cik is the holder's CIK. company_ 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_.
A page can be shorter than limit. Keep following next_ until it is null.
MCP: tool filings_.
Parameters
| Parameter | Where | Required | Type | Meaning |
|---|---|---|---|---|
cik | path | Yes | string | The holder's CIK, one to ten digits. |
schedule | query | No | one of 13D, 13G | Only 13D (holders that may seek control) or 13G (passive holders). |
type | query | No | one of activist, passive | activist is the same as 13D and passive the same as 13G. When schedule is also sent, the two must agree. |
history | query | No | boolean | false (the default) answers the current stakes. true lists every filing, newest first. |
is_ | query | No | boolean | Only with history=true. true keeps the latest filing of each stake and false keeps the earlier ones. |
filed | query | No | date | Only filings made on this day. |
filed_ | query | No | date | Same as filed_. |
filed_ | query | No | date | Same as filed_. |
filed_ | query | No | date | Only filings made after this day. |
filed_ | query | No | date | Only filings made on or after this day. |
filed_ | query | No | date | Only filings made before this day. |
filed_ | query | No | date | Only filings made on or before this day. |
cursor | query | No | string | next_ of the previous page, with the same other parameters. |
limit | query | No | integer | Rows per page. Default 50, at most 1000. |
ticker | query | No | string | Only stakes in the company with this ticker. |
Response fields
| Field | Type | Sent | Meaning |
|---|---|---|---|
id | string | Always | The company id on the owners route, and the holder id on the stakes route. |
holder | string | Optional | Name of the holder. |
stakes | list of object | Always | The stakes of the holder, newest first. |
stakes[].filing_ | string | Always | Id of the filing the row comes from. |
stakes[].form | one of 13D, 13D/A, 13G, 13G/A | Always | The schedule and whether it amends an earlier one: 13D, 13D/, 13G or 13G/. |
stakes[].filed | date | Always | Day the filing was made. |
stakes[].accepted | date-time | Optional | The moment the SEC accepted the filing. |
stakes[].event_ | date | Optional | Date of the event that required the filing. |
stakes[].amendment_ | integer | Optional | Number of the amendment, when the filing states it. |
stakes[].filer_ | string | Optional | Id of the first filer of the filing, the firm that submitted it. |
stakes[].filer | string | Optional | Name of the first filer. It can differ from the reporting person. |
stakes[].holder_ | string | Optional | Id of the reporting person. An individual has none. |
stakes[].holder | string | Always | Name of the reporting person. |
stakes[].holder_ | string | Optional | Cover page code of the person: IN individual, CO corporation, PN partnership, IA investment adviser, HC holding company, BK bank, and others. |
stakes[].citizenship | string | Optional | Citizenship or place of organization of the person. |
stakes[].class_ | string | Optional | Title of the class of shares. |
stakes[].shares | string | Optional | Shares the person reports owning. On a joint filing do not add these across people. Use group_. |
stakes[].percent_ | string | Optional | Percent of the class the person reports owning. |
stakes[].sole_ | string | Optional | Shares the person alone can vote. |
stakes[].shared_ | string | Optional | Shares the person shares the vote on. |
stakes[].sole_ | string | Optional | Shares the person alone can sell. |
stakes[].shared_ | string | Optional | Shares the person shares the power to sell. |
stakes[].group_ | one of a, b, ab | Optional | What 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[].rule | string | Optional | The rule a 13G was filed under: 13d-1(b), 13d-1(c) or 13d-1(d). |
stakes[].funds | string | Optional | A 13D's source of funds code, for example WC, AF, PF or OO. |
stakes[].type | one of activist, passive | Optional | activist for Schedule 13D and passive for Schedule 13G. |
stakes[].legal_ | always true | Optional | True when the cover box for legal proceedings is ticked. |
stakes[].excludes_ | always true | Optional | True when the cover box for excluding certain shares is ticked. |
stakes[].previously_ | always true | Optional | True when the filing carries the previously filed flag. |
stakes[].issuer_ | string | Optional | Address of the company, as filed. |
stakes[].purpose | string | Optional | A 13D's Item 4, the purpose of the transaction. Cut at 4,000 characters. |
stakes[].items | object | Optional | The 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[].joint | integer | Optional | How many people the filing names. |
stakes[].repeat | always true | Optional | True when the person states a figure that an earlier person on the filing already stated. |
stakes[].group_ | string | Optional | On a joint filing, the largest aggregate any of its people reports. Read the group's figure here. |
stakes[].is_ | boolean | Always | True on the latest filing of the stake among the filings the request keeps. |
stakes[].exit | always true | Optional | True when the filing reports the holder at 5% or less, or with no shares. |
stakes[].superseded | always true | Optional | True on the latest filing of a stake that a later filing of the same filer group no longer lists. |
stakes[].company_ | string | Always | Id of the company the stake is in. |
stakes[].company | string | Optional | Name of the company the stake is in. |
next_ | string | Always | Pass as cursor to read the next page. Always sent; null on the last page. |
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/investors/0000102909/beneficial-ownership?filed_lte=2025-10-31&limit=1"{
"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_.
MCP: tool filings_.
Parameters
| Parameter | Where | Required | Type | Meaning |
|---|---|---|---|---|
name | query | Yes | string | The first letters of the name. At least two letters or digits. |
country | query | No | string | Three-letter country code of the registry to search. Left out means USA. A country the route does not cover is 404 not_covered. |
limit | query | No | integer | Hits to return. Default 20, at most 100. |
Response fields
| Field | Type | Sent | Meaning |
|---|---|---|---|
filers | list of object | Always | The filers whose name starts with the text. |
filers[].id | string | Always | The filer's id, to pass as cik on the stakes route. |
filers[].name | string | Always | A name the filer used in a filing. |
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/beneficial-ownership/filers?name=vanguard&limit=3"{
"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_ on the owners route.
Returns the id to pass as company_ on the owners route.
MCP: tool filings_.
Parameters
| Parameter | Where | Required | Type | Meaning |
|---|---|---|---|---|
name | query | Yes | string | The first letters of the name. At least two letters or digits. |
country | query | No | string | Three-letter country code of the registry to search. Left out means USA. A country the route does not cover is 404 not_covered. |
limit | query | No | integer | Hits to return. Default 20, at most 100. |
Response fields
| Field | Type | Sent | Meaning |
|---|---|---|---|
companies | list of object | Always | The companies whose name starts with the text. |
companies[].id | string | Always | The company's id, to pass as company_ on the owners route. |
companies[].name | string | Always | Name of the company. |
curl -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/beneficial-ownership/companies?name=apple&limit=2"{
"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_. See Errors and credits for the shape and the credit headers. Failed requests are not charged.
| Code | Status | Meaning |
|---|---|---|
invalid_ | 400 | A parameter is missing, unknown, repeated or outside its range. |
invalid_ | 400 | The cursor is not one this request returned, or it comes from a different request. |
invalid_ | 400 | The name has fewer than two letters or digits once words like Inc are left out. |
company_ | 404 | No company matches the id. |
investor_ | 404 | No Schedule 13D or 13G filer matches the CIK. |
not_ | 404 | The market, country or company is not covered yet. |
insufficient_ | 402 | Your credit balance is less than the request costs. |
company_ | 503 | The filings behind this route cannot be read right now. Try again shortly. |
Was this page helpful?