curl --request GET \
--url https://api.financialdatasets.ai/insider-ownership \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/insider-ownership"
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/insider-ownership', 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/insider-ownership",
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/insider-ownership"
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/insider-ownership")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/insider-ownership")
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{
"insider_ownership": [
{
"ticker": "<string>",
"issuer": "<string>",
"name": "<string>",
"title": "<string>",
"is_board_director": true,
"is_officer": true,
"is_ten_percent_owner": true,
"form_type": "<string>",
"filing_date": "2023-12-25",
"as_of_date": "2023-12-25",
"accession_number": "<string>",
"holding_type": "common",
"security_title": "<string>",
"shares_owned": 123,
"direct_or_indirect": "<string>",
"nature_of_ownership": "<string>",
"conversion_or_exercise_price": 123,
"exercise_date": "2023-12-25",
"expiration_date": "2023-12-25",
"underlying_security_title": "<string>",
"underlying_security_shares": 123
}
],
"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."
}Insider Ownership
See what company insiders actually own, from SEC Forms 3 and 5. Initial ownership statements and annual holdings for officers, directors, and 10% owners.
curl --request GET \
--url https://api.financialdatasets.ai/insider-ownership \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.financialdatasets.ai/insider-ownership"
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/insider-ownership', 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/insider-ownership",
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/insider-ownership"
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/insider-ownership")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.financialdatasets.ai/insider-ownership")
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{
"insider_ownership": [
{
"ticker": "<string>",
"issuer": "<string>",
"name": "<string>",
"title": "<string>",
"is_board_director": true,
"is_officer": true,
"is_ten_percent_owner": true,
"form_type": "<string>",
"filing_date": "2023-12-25",
"as_of_date": "2023-12-25",
"accession_number": "<string>",
"holding_type": "common",
"security_title": "<string>",
"shares_owned": 123,
"direct_or_indirect": "<string>",
"nature_of_ownership": "<string>",
"conversion_or_exercise_price": 123,
"exercise_date": "2023-12-25",
"expiration_date": "2023-12-25",
"underlying_security_title": "<string>",
"underlying_security_shares": 123
}
],
"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."
}Overview
The insider ownership API gives you the ownership statements of public company insiders: what CEOs, CFOs, directors, and 10% owners actually hold, not just what they traded. It is sourced from SEC Form 3 (an insider’s initial statement of ownership, filed when they become an insider) and Form 5 (the annual statement). It complements the insider trades API, which covers the buys and sells in between: trades are the events, ownership statements are the state. You can answer questions like:- What did a new director own on the day they joined the board?
- What positions does an insider report in their annual statement, including options and RSUs?
- Which insiders hold their shares indirectly, through trusts or LLCs?
Coverage
| Companies | Insiders | History | Updated |
|---|---|---|---|
| 6,500+ | 40,000+ | Since January 2021 | Daily |
Available Tickers
You can fetch a list of companies with insider ownership statements with aGET request to:
https://api.financialdatasets.ai/insider-ownership/tickers/
Available Insiders
You can fetch a list of insider names for a given ticker with aGET request to:
https://api.financialdatasets.ai/insider-ownership/names/?ticker=AAPL
Getting Started
There are only 3 steps for making a successful API call:- Add your API key to the header of the request as
X-API-KEY. - Add query params like
tickerandlimitto filter the data. - Execute the API request.
Filtering the Data
You can filter the data byticker (required), plus name, form_type, limit, and filing_date.
Note: by default, limit is 10 (max 1000), name is null, and form_type is null.
The name parameter matches insider names (case-insensitive contains). You can get the list of available names for a ticker from the /names endpoint above.
The form_type parameter filters to 3 (initial ownership statements), 5 (annual statements), or their amendments 3/A and 5/A.
The filing_date parameter is used to filter by when filings were submitted. For example, you can include filters like filing_date_lte=2026-06-30 and filing_date_gte=2026-01-01 to get statements filed in the first half of 2026.
The available filing_date operations are:
filing_date_ltefiling_date_ltfiling_date_gtefiling_date_gtfiling_date
Example
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'AAPL' # stock ticker
limit = 50 # number of rows to return
# create the URL
url = (
f'https://api.financialdatasets.ai/insider-ownership'
f'?ticker={ticker}'
f'&limit={limit}'
)
# make API request
response = requests.get(url, headers=headers)
# parse insider_ownership from the response
insider_ownership = response.json().get('insider_ownership')
Example (with name)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'AAPL' # stock ticker
name = 'cook' # insider name (case-insensitive contains)
# create the URL
url = (
f'https://api.financialdatasets.ai/insider-ownership'
f'?ticker={ticker}'
f'&name={name}'
)
# make API request
response = requests.get(url, headers=headers)
# parse insider_ownership from the response
insider_ownership = response.json().get('insider_ownership')
Example (initial statements only)
import requests
# add your API key to the headers
headers = {
"X-API-KEY": "your_api_key_here"
}
# set your query params
ticker = 'AAPL' # stock ticker
form_type = '3' # Form 3: what a new insider owned on day one
# create the URL
url = (
f'https://api.financialdatasets.ai/insider-ownership'
f'?ticker={ticker}'
f'&form_type={form_type}'
)
# make API request
response = requests.get(url, headers=headers)
# parse insider_ownership from the response
insider_ownership = response.json().get('insider_ownership')
Authorizations
API key for authentication.
Query Parameters
The ticker symbol of the company.
Filter by insider name (case-insensitive contains). Use the /insider-ownership/names endpoint to get available names for a ticker.
Filter by SEC form type: 3 for initial ownership statements, 5 for annual statements (or their amendments 3/A, 5/A).
3, 3/A, 5, 5/A Filter by exact filing date in YYYY-MM-DD format.
Filter by filing date greater than or equal to this date (YYYY-MM-DD).
Filter by filing date less than or equal to this date (YYYY-MM-DD).
Filter by filing date greater than this date (YYYY-MM-DD).
Filter by filing date less than this date (YYYY-MM-DD).
The total number of rows to return (default: 10; 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.
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.