Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions eodhd/APIs/SecFilings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# APIs/SecFilings.py

from .BaseAPI import BaseAPI


class SecFilingsAPI(BaseAPI):
"""
Wrapper for the SEC Filings API:

GET /api/sec-filings/{symbol} overview (counts + latest per form type)
GET /api/sec-filings/{symbol}/10k annual reports (10-K), paginated
GET /api/sec-filings/{symbol}/10q quarterly reports (10-Q), paginated
GET /api/sec-filings/{symbol}/8k material events (8-K), paginated

Notes:
- The overview endpoint returns { data, meta, links } where data is a dict
{ ticker, exchange, name, cik, filings } and filings is keyed by form type
("10k"/"10q"/"8k"/"form4"), each { count, latest, url }. meta and links are
empty and there is no pagination.
- The 10-K, 10-Q and 8-K endpoints return { data, meta, links } with data as a
list of rows and meta { total, page: { offset, limit } }; links.next is a
URL string or null.
- Pagination uses page[offset] (>= 0, default 0) and page[limit] (1..100,
default 20).
- Any numeric field in a row may be null.
- Responses are parsed JSON.

Docs: https://eodhd.com/financial-apis/sec-filings-api
"""

@staticmethod
def _validate_symbol(symbol) -> str:
"""Validate a ticker symbol and return it stripped (e.g. 'AAPL.US')."""
if symbol is None or not isinstance(symbol, str) or symbol.strip() == "":
raise ValueError("Parameter 'symbol' is required and must be a non-empty string (e.g. 'AAPL.US').")
return symbol.strip()

def get_sec_filings_overview(self, api_token: str, symbol: str):
"""
GET /api/sec-filings/{symbol}

Overview of a company's SEC filings: counts, latest date and URL per form
type. Parameterless (no pagination).

Params:
symbol: ticker symbol (e.g. "AAPL.US").

Response data (dict): { ticker, exchange, name, cik,
filings: { "10k": {count, latest, url}, "10q": {...},
"8k": {...}, "form4": {...} } }.
"""
symbol = self._validate_symbol(symbol)

return self._rest_get_method(
api_key=api_token,
endpoint="sec-filings",
uri=symbol,
querystring="",
)

def get_sec_filings_10k(self, api_token: str, symbol: str,
page_offset: int = 0, page_limit: int = 20):
"""
GET /api/sec-filings/{symbol}/10k

Annual reports (10-K) with parsed financials, paginated.

Params:
symbol: ticker symbol (e.g. "AAPL.US").
page_offset: >= 0 (default 0). page_limit: 1..100 (default 20).

Response data[] row: accession_number, filed_at, period_of_report,
fiscal_year_end plus the parsed income-statement, balance-sheet and
cash-flow financials (any numeric may be null).
"""
symbol = self._validate_symbol(symbol)

query_string = self._pagination(page_offset, page_limit)

return self._rest_get_method(
api_key=api_token,
endpoint="sec-filings",
uri=f"{symbol}/10k",
querystring=query_string,
)

def get_sec_filings_10q(self, api_token: str, symbol: str,
page_offset: int = 0, page_limit: int = 20):
"""
GET /api/sec-filings/{symbol}/10q

Quarterly reports (10-Q) with parsed financials, paginated.

Same shape as the 10-K rows except the period metadata is
fiscal_quarter_end (str) instead of fiscal_year_end, plus fiscal_quarter
(int).

Params:
symbol: ticker symbol (e.g. "AAPL.US").
page_offset: >= 0 (default 0). page_limit: 1..100 (default 20).
"""
symbol = self._validate_symbol(symbol)

query_string = self._pagination(page_offset, page_limit)

return self._rest_get_method(
api_key=api_token,
endpoint="sec-filings",
uri=f"{symbol}/10q",
querystring=query_string,
)

def get_sec_filings_8k(self, api_token: str, symbol: str,
page_offset: int = 0, page_limit: int = 20):
"""
GET /api/sec-filings/{symbol}/8k

Material events (8-K), paginated.

Params:
symbol: ticker symbol (e.g. "AAPL.US").
page_offset: >= 0 (default 0). page_limit: 1..100 (default 20).

Response data[] item: { accession_number, filed_at, period_of_report,
items: [str], item_sections: [{item, title, text}],
exhibits: [{number, description}] }.
"""
symbol = self._validate_symbol(symbol)

query_string = self._pagination(page_offset, page_limit)

return self._rest_get_method(
api_key=api_token,
endpoint="sec-filings",
uri=f"{symbol}/8k",
querystring=query_string,
)
1 change: 1 addition & 0 deletions eodhd/APIs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .SanctionsAPI import SanctionsAPI
from .InterestRatesAPI import InterestRatesAPI
from .RealEstate import RealEstateAPI
from .SecFilings import SecFilingsAPI

#Marketplace endpoints
from .MPIndexComponentsAPI import MPIndexComponentsAPI
Expand Down
72 changes: 72 additions & 0 deletions eodhd/apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from eodhd.APIs import SanctionsAPI
from eodhd.APIs import InterestRatesAPI
from eodhd.APIs import RealEstateAPI
from eodhd.APIs import SecFilingsAPI

#Marketplace endpoints
from eodhd.APIs import MPIndexComponentsAPI
Expand Down Expand Up @@ -2018,6 +2019,77 @@ def get_real_estate_detailed_series(self, code):
api_token=self._api_key, code=code,
)

def get_sec_filings_overview(self, symbol):
"""
SEC Filings API: overview of a company's filings (counts, latest date and
URL per form type: 10-K, 10-Q, 8-K, Form 4).
Endpoint: GET /api/sec-filings/{symbol}

Args:
symbol [REQUIRED] - ticker symbol, e.g. "AAPL.US"
Returns: dict envelope { data, meta, links } where data is a dict
{ ticker, exchange, name, cik, filings }
For more information visit: https://eodhd.com/financial-apis/sec-filings-api
"""
api_call = SecFilingsAPI(session=self._session, timeout=self._timeout)
return api_call.get_sec_filings_overview(
api_token=self._api_key, symbol=symbol,
)

def get_sec_filings_10k(self, symbol, page_offset=0, page_limit=20):
"""
SEC Filings API: annual reports (10-K) with parsed financials, paginated.
Endpoint: GET /api/sec-filings/{symbol}/10k

Args:
symbol [REQUIRED] - ticker symbol, e.g. "AAPL.US"
page_offset [OPTIONAL] - >= 0 (default 0)
page_limit [OPTIONAL] - 1..100 (default 20)
Returns: dict envelope { data, meta, links }
For more information visit: https://eodhd.com/financial-apis/sec-filings-api
"""
api_call = SecFilingsAPI(session=self._session, timeout=self._timeout)
return api_call.get_sec_filings_10k(
api_token=self._api_key, symbol=symbol,
page_offset=page_offset, page_limit=page_limit,
)

def get_sec_filings_10q(self, symbol, page_offset=0, page_limit=20):
"""
SEC Filings API: quarterly reports (10-Q) with parsed financials, paginated.
Endpoint: GET /api/sec-filings/{symbol}/10q

Args:
symbol [REQUIRED] - ticker symbol, e.g. "AAPL.US"
page_offset [OPTIONAL] - >= 0 (default 0)
page_limit [OPTIONAL] - 1..100 (default 20)
Returns: dict envelope { data, meta, links }
For more information visit: https://eodhd.com/financial-apis/sec-filings-api
"""
api_call = SecFilingsAPI(session=self._session, timeout=self._timeout)
return api_call.get_sec_filings_10q(
api_token=self._api_key, symbol=symbol,
page_offset=page_offset, page_limit=page_limit,
)

def get_sec_filings_8k(self, symbol, page_offset=0, page_limit=20):
"""
SEC Filings API: material events (8-K), paginated.
Endpoint: GET /api/sec-filings/{symbol}/8k

Args:
symbol [REQUIRED] - ticker symbol, e.g. "AAPL.US"
page_offset [OPTIONAL] - >= 0 (default 0)
page_limit [OPTIONAL] - 1..100 (default 20)
Returns: dict envelope { data, meta, links }
For more information visit: https://eodhd.com/financial-apis/sec-filings-api
"""
api_call = SecFilingsAPI(session=self._session, timeout=self._timeout)
return api_call.get_sec_filings_8k(
api_token=self._api_key, symbol=symbol,
page_offset=page_offset, page_limit=page_limit,
)


class ScannerClient:
"""Scanner class"""
Expand Down
Loading