EntityFacts API Reference
Complete API documentation for the enhanced EntityFacts system, including all classes, methods, and data models.
Overview
The EntityFacts API provides structured access to SEC company financial data with AI-ready features, powerful querying capabilities, and professional formatting. The system consists of several key components:
- EntityFacts - Main class for accessing company facts
- FactQuery - Fluent query builder for advanced filtering
- FinancialStatement - Formatted display wrapper for financial data
- FinancialFact - Individual fact data model with rich metadata
EntityFacts Class
The main entry point for accessing company financial facts.
Constructor
EntityFacts(cik: int, name: str, facts: List[FinancialFact])
Parameters:
- cik
(int): Company CIK number
- name
(str): Company name
- facts
(List[FinancialFact]): List of financial facts
Properties
Core Properties
cik: int
The company's CIK (Central Index Key) number.
facts = company.facts
print(facts.cik) # 320193
name: str
The company's official name.
facts = company.facts
print(facts.name) # "Apple Inc."
DEI Properties
shares_outstanding: Optional[float]
Number of common shares outstanding.
shares = facts.shares_outstanding
if shares:
print(f"Shares Outstanding: {shares:,.0f}")
public_float: Optional[float]
Public float value in dollars.
float_val = facts.public_float
if float_val:
print(f"Public Float: ${float_val:,.0f}")
shares_outstanding_fact: Optional[FinancialFact]
Full fact object for shares outstanding with metadata.
fact = facts.shares_outstanding_fact
if fact:
print(f"Shares: {fact.get_formatted_value()} as of {fact.period_end}")
public_float_fact: Optional[FinancialFact]
Full fact object for public float with metadata.
fact = facts.public_float_fact
if fact:
print(f"Float: {fact.get_formatted_value()} as of {fact.period_end}")
Core Methods
Query Interface
query() -> FactQuery
Start building a facts query using the fluent interface.
query = facts.query()
results = query.by_concept('Revenue').latest(4)
Returns: FactQuery builder instance
get_fact(concept: str, period: Optional[str] = None) -> Optional[FinancialFact]
Get a single fact by concept name.
revenue_fact = facts.get_fact('Revenue')
q1_revenue = facts.get_fact('Revenue', '2024-Q1')
Parameters:
- concept
(str): Concept name or label (case-insensitive)
- period
(str, optional): Period in format "YYYY-QN" or "YYYY-FY"
Returns: Most recent matching fact or None
time_series(concept: str, periods: int = 20) -> pd.DataFrame
Get time series data for a concept.
revenue_ts = facts.time_series('Revenue', periods=8)
Parameters:
- concept
(str): Concept name or label
- periods
(int): Number of periods to retrieve (default: 20)
Returns: DataFrame with time series data
Financial Statement Methods
income_statement(periods: int = 4,
period_length: Optional[int] = None,
as_dataframe: bool = False,
annual: bool = True)
Get income statement facts formatted as a financial statement.
# Default: 4 annual periods, formatted display
stmt = facts.income_statement()
# 8 quarterly periods as DataFrame
df = facts.income_statement(periods=8, annual=False, as_dataframe=True)
Parameters:
- periods
(int): Number of periods to retrieve (default: 4)
- period_length
(int, optional): Filter by period length in months (3=quarterly, 12=annual)
- as_dataframe
(bool): If True, return DataFrame; if False, return FinancialStatement (default: False)
- annual
(bool): If True, prefer annual periods; if False, prefer quarterly (default: True)
Returns: FinancialStatement or DataFrame
balance_sheet(periods: int = 4, as_of: Optional[date] = None, as_dataframe: bool = False, annual: bool = True)
Get balance sheet facts for periods or point-in-time.
# Multi-period balance sheet
stmt = facts.balance_sheet(periods=4)
# Point-in-time snapshot
snapshot = facts.balance_sheet(as_of=date(2024, 12, 31))
Parameters:
- periods
(int): Number of periods to retrieve (default: 4)
- as_of
(date, optional): Get snapshot as of specific date
- as_dataframe
(bool): If True, return DataFrame; if False, return FinancialStatement (default: False)
- annual
(bool): If True, prefer annual periods (default: True)
Returns: FinancialStatement or DataFrame
cash_flow(periods: int = 4, period_length: Optional[int] = None, as_dataframe: bool = False, annual: bool = True)
Get cash flow statement facts.
# Annual cash flow trends
stmt = facts.cash_flow(periods=5, annual=True)
Parameters:
- periods
(int): Number of periods to retrieve (default: 4)
- period_length
(int, optional): Filter by period length in months
- as_dataframe
(bool): If True, return DataFrame; if False, return FinancialStatement (default: False)
- annual
(bool): If True, prefer annual periods (default: True)
Returns: FinancialStatement or DataFrame
DEI Methods
dei_facts(as_of: Optional[date] = None) -> pd.DataFrame
Get Document and Entity Information facts.
# Latest DEI facts
dei = facts.dei_facts()
# DEI facts as of specific date
dei = facts.dei_facts(as_of=date(2024, 12, 31))
Parameters:
- as_of
(date, optional): Get facts as of specific date
Returns: DataFrame with DEI facts
entity_info() -> Dict[str, Any]
Get key entity information as a clean dictionary.
info = facts.entity_info()
print(info['entity_name'])
print(info['shares_outstanding'])
Returns: Dictionary with entity information
AI/LLM Methods
to_llm_context(focus_areas: Optional[List[str]] = None, time_period: str = "recent") -> Dict[str, Any]
Generate comprehensive context for LLM analysis.
context = facts.to_llm_context(
focus_areas=['profitability', 'growth'],
time_period='5Y'
)
Parameters:
- focus_areas
(List[str], optional): Areas to emphasize (['profitability', 'growth', 'liquidity'])
- time_period
(str): Time period to analyze ('recent', '5Y', '10Y', 'all') (default: 'recent')
Returns: Dictionary with structured LLM context
to_agent_tools() -> List[Dict[str, Any]]
Export facts as MCP-compatible tools for AI agents.
tools = facts.to_agent_tools()
Returns: List of tool definitions
Magic Methods
__len__() -> int
Get total number of facts.
total_facts = len(facts)
__iter__() -> Iterator[FinancialFact]
Iterate over all facts.
for fact in facts:
print(f"{fact.concept}: {fact.numeric_value}")
FactQuery Class
Fluent query builder for advanced fact filtering and analysis.
Constructor
Created via EntityFacts.query()
method. Do not instantiate directly.
Filtering Methods
Concept Filtering
by_concept(concept: str, exact: bool = False) -> FactQuery
Filter by concept name or pattern.
# Fuzzy matching (default)
revenue_facts = query.by_concept('Revenue')
# Exact matching
exact_revenue = query.by_concept('us-gaap:Revenue', exact=True)
Parameters:
- concept
(str): Concept name or label to match
- exact
(bool): If True, require exact match (default: False)
by_label(label: str, fuzzy: bool = True) -> FactQuery
Filter by human-readable label.
# Fuzzy label matching
facts = query.by_label('Total Revenue', fuzzy=True)
# Exact label matching
facts = query.by_label('Revenue', fuzzy=False)
Parameters:
- label
(str): Label to match
- fuzzy
(bool): Use fuzzy matching (default: True)
Time-Based Filtering
by_fiscal_year(year: int) -> FactQuery
Filter by fiscal year.
fy2024_facts = query.by_fiscal_year(2024)
Parameters:
- year
(int): Fiscal year to filter by
by_fiscal_period(period: str) -> FactQuery
Filter by fiscal period.
q1_facts = query.by_fiscal_period('Q1')
fy_facts = query.by_fiscal_period('FY')
Parameters:
- period
(str): Fiscal period ('FY', 'Q1', 'Q2', 'Q3', 'Q4')
by_period_length(months: int) -> FactQuery
Filter by period length in months.
# Quarterly periods (3 months)
quarterly = query.by_period_length(3)
# Annual periods (12 months)
annual = query.by_period_length(12)
Parameters:
- months
(int): Period length (3=quarterly, 12=annual, 9=YTD)
date_range(start: date, end: date) -> FactQuery
Filter by date range.
recent_facts = query.date_range(
start=date(2023, 1, 1),
end=date(2024, 12, 31)
)
Parameters:
- start
(date): Start date (inclusive)
- end
(date): End date (inclusive)
as_of(as_of_date: date) -> FactQuery
Get facts as of specific date (point-in-time).
snapshot = query.as_of(date(2024, 6, 30))
Parameters:
- as_of_date
(date): Date for point-in-time view
Statement and Form Filtering
by_statement_type(statement_type: str) -> FactQuery
Filter by financial statement type.
income_facts = query.by_statement_type('IncomeStatement')
balance_facts = query.by_statement_type('BalanceSheet')
cash_facts = query.by_statement_type('CashFlow')
Parameters:
- statement_type
(str): Statement type ('IncomeStatement', 'BalanceSheet', 'CashFlow')
by_form_type(form_type: Union[str, List[str]]) -> FactQuery
Filter by SEC form type.
# Single form type
annual_facts = query.by_form_type('10-K')
# Multiple form types
periodic_facts = query.by_form_type(['10-K', '10-Q'])
Parameters:
- form_type
(str or List[str]): Form type(s) to filter by
Quality Filtering
high_quality_only() -> FactQuery
Filter to only high-quality, audited facts.
quality_facts = query.high_quality_only()
min_confidence(threshold: float) -> FactQuery
Filter by minimum confidence score.
confident_facts = query.min_confidence(0.9)
Parameters:
- threshold
(float): Minimum confidence score (0.0 to 1.0)
Special Queries
latest_instant() -> FactQuery
Filter to most recent instant facts (for balance sheet items).
latest_balance = query.by_statement_type('BalanceSheet').latest_instant()
latest_periods(n: int = 4, annual: bool = True) -> FactQuery
Get facts from the n most recent periods.
# Latest 4 annual periods only
recent = query.latest_periods(4, annual=True)
# Latest 8 periods, any type
recent = query.latest_periods(8, annual=False)
Parameters:
- n
(int): Number of recent periods (default: 4)
- annual
(bool): If True, only use annual periods; if False, use all period types (default: True)
Sorting and Limiting
sort_by(field: str, ascending: bool = True) -> FactQuery
Sort results by field.
# Sort by filing date (newest first)
sorted_facts = query.sort_by('filing_date', ascending=False)
# Sort by fiscal year
sorted_facts = query.sort_by('fiscal_year')
Parameters:
- field
(str): Field name to sort by
- ascending
(bool): Sort order (default: True)
latest(n: int = 1) -> List[FinancialFact]
Get the n most recent facts.
latest_revenue = query.by_concept('Revenue').latest(5)
Parameters:
- n
(int): Number of facts to return (default: 1)
Returns: List of facts (executes query immediately)
Execution Methods
execute() -> List[FinancialFact]
Execute query and return matching facts.
facts = query.by_concept('Revenue').by_fiscal_year(2024).execute()
Returns: List of FinancialFact objects
count() -> int
Get count of facts matching current filters.
revenue_count = query.by_concept('Revenue').count()
Returns: Number of matching facts
Output Methods
to_dataframe(*columns) -> pd.DataFrame
Convert results to pandas DataFrame.
# All columns
df = query.by_concept('Revenue').to_dataframe()
# Selected columns
df = query.by_concept('Revenue').to_dataframe(
'label', 'numeric_value', 'fiscal_period'
)
Parameters:
- *columns
(str): Optional column names to include
Returns: DataFrame with query results
pivot_by_period(return_statement: bool = True) -> Union[FinancialStatement, pd.DataFrame]
Pivot facts to show concepts as rows and periods as columns.
# Formatted financial statement
stmt = query.by_statement_type('IncomeStatement').pivot_by_period()
# Raw DataFrame
df = query.by_statement_type('IncomeStatement').pivot_by_period(return_statement=False)
Parameters:
- return_statement
(bool): If True, return FinancialStatement; if False, return DataFrame (default: True)
Returns: FinancialStatement or DataFrame
to_llm_context() -> List[Dict[str, Any]]
Convert results to LLM-friendly context.
llm_data = query.by_concept('Revenue').to_llm_context()
Returns: List of fact contexts for LLM consumption
FinancialStatement Class
Wrapper around pandas DataFrame for financial statements with intelligent formatting.
Constructor
FinancialStatement(
data: pd.DataFrame,
statement_type: str,
entity_name: str = "",
period_lengths: Optional[List[str]] = None,
mixed_periods: bool = False
)
Parameters:
- data
(pd.DataFrame): Financial data
- statement_type
(str): Statement type
- entity_name
(str): Company name
- period_lengths
(List[str], optional): Period lengths in data
- mixed_periods
(bool): Whether data contains mixed period lengths
Properties
shape: tuple
Shape of the underlying DataFrame.
stmt = company.income_statement()
print(stmt.shape) # (10, 4)
columns: pd.Index
Column names of the statement.
periods = stmt.columns
print(list(periods)) # ['FY 2024', 'FY 2023', 'FY 2022', 'FY 2021']
index: pd.Index
Row labels (concept names).
concepts = stmt.index
print(list(concepts)) # ['Revenue', 'Cost of Revenue', 'Gross Profit', ...]
empty: bool
Whether the statement is empty.
if not stmt.empty:
print("Statement has data")
Methods
to_numeric() -> pd.DataFrame
Get underlying numeric DataFrame for calculations.
stmt = company.income_statement()
numeric_data = stmt.to_numeric()
growth_rates = numeric_data.pct_change(axis=1)
Returns: DataFrame with original numeric values
get_concept(concept_name: str) -> Optional[pd.Series]
Get data for specific concept across all periods.
revenue_series = stmt.get_concept('Revenue')
if revenue_series is not None:
print(revenue_series)
Parameters:
- concept_name
(str): Name of concept to retrieve
Returns: Series with values across periods, or None
calculate_growth(concept_name: str, periods: int = 2) -> Optional[pd.Series]
Calculate period-over-period growth for a concept.
revenue_growth = stmt.calculate_growth('Revenue', periods=1)
Parameters:
- concept_name
(str): Name of concept
- periods
(int): Number of periods for growth calculation (default: 2)
Returns: Series with growth rates, or None
format_value(value: float, concept_label: str) -> str
Format a single value based on its concept.
formatted = stmt.format_value(1234567, 'Revenue')
print(formatted) # "$1,234,567"
Parameters:
- value
(float): Numeric value to format
- concept_label
(str): Label of financial concept
Returns: Formatted string
to_llm_context() -> Dict[str, Any]
Generate LLM-friendly context from the statement.
context = stmt.to_llm_context()
Returns: Dictionary with structured financial data
Display Methods
The FinancialStatement class provides rich display capabilities:
- Jupyter Notebooks: Automatic HTML rendering with professional styling
- Console: Formatted text output with proper alignment
- Rich Integration: Compatible with Rich library for enhanced terminal display
FinancialFact Class
Individual financial fact with rich metadata and AI-ready features.
Constructor
FinancialFact(
concept: str,
taxonomy: str,
label: str,
value: Union[float, int, str],
numeric_value: Optional[float],
unit: str,
scale: Optional[int] = None,
# ... additional parameters
)
Core Attributes
concept: str
Standardized concept identifier (e.g., 'us-gaap:Revenue').
taxonomy: str
Taxonomy namespace (us-gaap, ifrs, etc.).
label: str
Human-readable label.
value: Union[float, int, str]
The actual fact value.
numeric_value: Optional[float]
Numeric representation for calculations.
unit: str
Unit of measure (USD, shares, etc.).
scale: Optional[int]
Scale factor (1000, 1000000, etc.).
Temporal Attributes
period_start: Optional[date]
Period start date (for duration facts).
period_end: date
Period end date.
period_type: Literal['instant', 'duration']
Type of period.
fiscal_year: int
Fiscal year.
fiscal_period: str
Fiscal period (FY, Q1, Q2, Q3, Q4).
Filing Context
filing_date: date
Date the fact was filed with SEC.
form_type: str
SEC form type (10-K, 10-Q, etc.).
accession: str
SEC accession number.
Quality Indicators
data_quality: DataQuality
Data quality enum (HIGH, MEDIUM, LOW).
is_audited: bool
Whether the fact is from audited filing.
confidence_score: float
Confidence score (0.0 to 1.0).
AI-Ready Attributes
semantic_tags: List[str]
Semantic tags for AI processing.
business_context: str
Business context description.
Methods
to_llm_context() -> Dict[str, Any]
Generate rich context for LLM consumption.
fact = facts.get_fact('Revenue')
context = fact.to_llm_context()
print(context['concept'])
print(context['value'])
print(context['period'])
Returns: Dictionary with formatted context
get_formatted_value() -> str
Format the numeric value for display.
fact = facts.get_fact('Revenue')
formatted = fact.get_formatted_value()
print(formatted) # "365,817,000,000"
Returns: Formatted string representation
get_display_period_key() -> str
Generate display-friendly period key.
fact = facts.get_fact('Revenue')
period = fact.get_display_period_key()
print(period) # "Q1 2024"
Returns: Period key like "Q1 2024", "FY 2023"
EntityFactsParser Class
Parser for converting SEC JSON data to enhanced EntityFacts format.
Static Methods
parse_company_facts(facts_json: Dict[str, Any]) -> EntityFacts
Parse SEC company facts JSON to EntityFacts object.
from edgar.entity.parser import EntityFactsParser
# Download SEC JSON
facts_json = download_json(f"https://data.sec.gov/api/xbrl/companyfacts/CIK{cik:010d}.json")
# Parse to enhanced format
entity_facts = EntityFactsParser.parse_company_facts(facts_json)
Parameters:
- facts_json
(Dict): SEC company facts JSON data
Returns: EntityFacts object
Data Models
DataQuality Enum
Quality indicators for financial facts.
from edgar.entity.models import DataQuality
DataQuality.HIGH # Direct from XBRL, validated
DataQuality.MEDIUM # Derived or calculated
DataQuality.LOW # Estimated or inferred
ConceptMetadata Class
Metadata about financial concepts.
@dataclass
class ConceptMetadata:
concept: str
label: str
definition: str
parent_concepts: List[str]
child_concepts: List[str]
# ... additional fields
Error Handling
NoCompanyFactsFound Exception
Raised when company facts cannot be found.
from edgar.entity.core import NoCompanyFactsFound
try:
facts = get_company_facts(invalid_cik)
except NoCompanyFactsFound as e:
print(f"No facts found: {e.message}")
Type Hints
The API uses comprehensive type hints for better IDE support:
from typing import Optional, List, Dict, Any, Union
from datetime import date
from edgar.entity.entity_facts import EntityFacts
from edgar.entity.models import FinancialFact
from edgar.entity.query import FactQuery
from edgar.entity.statement import FinancialStatement
Usage Patterns
Method Chaining
All query methods return the query object for chaining:
results = facts.query()\
.by_concept('Revenue')\
.by_fiscal_year(2024)\
.by_form_type('10-K')\
.sort_by('filing_date')\
.execute()
Error Handling
The API uses graceful error handling:
# Methods return None instead of raising exceptions
stmt = company.income_statement() # Returns None if no data
if stmt:
# Process statement
pass
Performance Considerations
- Use specific filters for better performance
- Leverage caching by reusing EntityFacts objects
- Use
count()
for existence checks before loading data - Prefer
latest()
overexecute()
when you need recent data only
This API reference documents EdgarTools EntityFacts system. For usage examples and tutorials, see the Company Facts Guide.