Get SEC financial statements as JSON
Resolve the ticker to a CIK with GET /v1/sec/companies/search?ticker=AAPL, then call GET /v1/sec/companies/{cik}/financials?metric=revenue,net_income,total_assets&period=annual. You get one JSON series per metric, each value as the company filed it in XBRL with its 10-K or 10-Q, the XBRL concept it came from, the accession number and a link to the EDGAR filing index. Agents can make the same call with the get_sec_company_financials MCP tool.
By New Odyssey · Published · Markdown
What you can request
Eight standardised metrics, taken from the XBRL financial data that registrants file with their 10-K and 10-Q reports. Values are in whole units (dollars, not thousands).
| Metric | Unit | Kind |
|---|---|---|
revenue | USD | Duration (a fiscal year or quarter) |
net_income | USD | Duration |
total_assets | USD | Point in time (period_start is null) |
total_liabilities | USD | Point in time |
stockholders_equity | USD | Point in time |
operating_cash_flow | USD | Duration; quarterly values are usually year-to-date (is_ytd: true) |
eps_diluted | USD/shares | Duration |
shares_outstanding | shares | Point in time; cover-page values are dated after the period end (as_of_date) |
period=annual (the default) reads 10-K and 10-K/A filings, fiscal period FY. period=quarterly reads 10-Q and 10-Q/A filings, fiscal periods Q1 to Q3. There is no Q4 value, because companies don't file a 10-Q for their fourth quarter, and we don't compute one from the annual figure. Fiscal years are the company's own: Apple's fiscal 2025 ended on 2025-09-27.
With curl
Every request needs an API key in the X-API-Key header. Create a free key and keep it in an environment variable. The examples read it from $OLYMPUS_API_KEY.
curl -s "https://api.olympus.new-odyssey.com/v1/sec/companies/search?ticker=AAPL" \
-H "X-API-Key: $OLYMPUS_API_KEY"curl -s "https://api.olympus.new-odyssey.com/v1/sec/companies/320193/financials?metric=revenue,net_income,total_assets&period=annual&fiscal_year_from=2025&fiscal_year_to=2025" \
-H "X-API-Key: $OLYMPUS_API_KEY"A CIK is accepted with or without leading zeros or a CIK prefix (320193, 0000320193, CIK0000320193). Responses always use the 10-digit form. The response below is abridged. The values are Apple's fiscal 2025 figures as filed in its 10-K (accession 0000320193-25-000079), as listed in the SEC's companyfacts data for CIK 0000320193.
{
"data": {
"cik": "0000320193",
"name": "Apple Inc.",
"period_type": "annual",
"fiscal_year_from": 2025,
"fiscal_year_to": 2025,
"series": [
{
"metric": "revenue",
"unit": "USD",
"values": [{
"fiscal_year": 2025,
"fiscal_period": "FY",
"period_start": "2024-09-29",
"period_end": "2025-09-27",
"value": 416161000000,
"unit": "USD",
"is_ytd": false,
"taxonomy": "us-gaap",
"concept": "RevenueFromContractWithCustomerExcludingAssessedTax",
"form": "10-K",
"filed_date": "2025-10-31",
"accession_number": "0000320193-25-000079",
"evidence_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019325000079/0000320193-25-000079-index.htm",
"is_restated": false,
"first_reported": { "value": 416161000000, "accession_number": "0000320193-25-000079", "filed_date": "2025-10-31" },
"provenance": { "dataset_id": "delphi.financial_metrics", "source_url": "https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json", … }
}]
},
{ "metric": "net_income", "unit": "USD", "values": [{ "fiscal_year": 2025, "value": 112010000000, "concept": "NetIncomeLoss", … }] },
{ "metric": "total_assets", "unit": "USD", "values": [{ "fiscal_year": 2025, "period_start": null, "period_end": "2025-09-27", "value": 359241000000, "concept": "Assets", … }] }
]
},
"meta": {
"request_id": "…",
"datasets": [{ "dataset_id": "delphi.financial_metrics", "published_at": "…", "freshness": "fresh" }]
}
}Without fiscal_year_from and fiscal_year_to you get a 10-fiscal-year window ending at the latest year available; a window can span at most 30 years. Metrics a company doesn't report come back as empty series, not errors.
With Python
The same two calls with requests:
import os
import requests
API = "https://api.olympus.new-odyssey.com"
HEADERS = {"X-API-Key": os.environ["OLYMPUS_API_KEY"]}
# 1. Ticker -> CIK. The lookup is exact and returns a list: a ticker can
# briefly belong to more than one registrant during a reorganisation.
r = requests.get(f"{API}/v1/sec/companies/search", params={"ticker": "AAPL"}, headers=HEADERS, timeout=30)
r.raise_for_status()
matches = r.json()["data"]
if len(matches) != 1:
raise SystemExit(f"expected one company, got {[(m['cik'], m['name']) for m in matches]}")
cik = matches[0]["cik"]
# 2. Annual revenue, net income and total assets.
r = requests.get(
f"{API}/v1/sec/companies/{cik}/financials",
params={"metric": "revenue,net_income,total_assets", "period": "annual",
"fiscal_year_from": 2021, "fiscal_year_to": 2025},
headers=HEADERS,
timeout=30,
)
r.raise_for_status()
for series in r.json()["data"]["series"]:
for v in series["values"]:
flag = " (restated)" if v["is_restated"] else ""
print(series["metric"], v["fiscal_year"], v["period_end"], v["value"], v["unit"], v["concept"], flag)To compare one metric across companies in a single request, use GET /v1/sec/financials/compare?cik=320193,789019&metric=revenue. Values are lined up by each company's fiscal year, not by calendar date, so check period_end when fiscal year ends differ.
From an AI agent (MCP)
The Olympus MCP server at https://mcp.olympus.new-odyssey.com/mcp exposes this as the get_sec_company_financials tool. It takes cik or ticker (exactly one), plus optional metrics, period, fiscal_year_from and fiscal_year_to. With a ticker it first resolves the CIK, which costs one extra metered request, and it fails with AMBIGUOUS_TICKER, listing the candidates, when a ticker maps to more than one CIK. Connect the server with your API key or by signing in with OAuth.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_sec_company_financials",
"arguments": {
"ticker": "AAPL",
"metrics": ["revenue", "net_income", "total_assets"],
"period": "annual",
"fiscal_year_from": 2021
}
}
}The result is the REST response's data, its provenance (meta.datasets and each value's provenance), the API's coverage limits and the request_id, so an agent can cite the filing behind each number. A prompt such as "What were Apple's revenue and net income for each of the last five fiscal years? Cite the 10-K for each." leads a client to call this tool.
How XBRL concepts map to metrics
Companies tag the same line item with different XBRL concepts. Each metric has a fixed, ordered list of us-gaap (or dei) concepts. For each period, the first concept in the list that has a value wins. The concept used is returned in concept on every value, so you can always see which line item a number came from.
| Metric | Concepts, in priority order |
|---|---|
revenue | Revenues, RevenueFromContractWithCustomerExcludingAssessedTax, RevenueFromContractWithCustomerIncludingAssessedTax, SalesRevenueNet |
net_income | NetIncomeLoss, ProfitLoss, NetIncomeLossAvailableToCommonStockholdersBasic |
total_assets | Assets |
total_liabilities | Liabilities |
stockholders_equity | StockholdersEquity, StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest |
operating_cash_flow | NetCashProvidedByUsedInOperatingActivities, NetCashProvidedByUsedInOperatingActivitiesContinuingOperations |
eps_diluted | EarningsPerShareDiluted, EarningsPerShareBasicAndDiluted |
shares_outstanding | dei:EntityCommonStockSharesOutstanding (cover page), CommonStockSharesOutstanding |
Nothing is derived. If a company doesn't tag Liabilities, total_liabilities is empty: we don't compute it as total liabilities and equity minus equity. Only facts without XBRL dimensions are used, so segment breakdowns are not included. Annual values must cover 350 to 380 days (52- and 53-week years), quarterly values 80 to 100 days.
Restatements and amendments
Each 10-K repeats earlier years as comparatives, and an amended filing (10-K/A, 10-Q/A) or a later report can change a figure that was already filed. For each period we serve the value from the latest filing and keep the first reported value next to it:
is_restated: truewhen the latest filed value differs from the first one reported for that period.first_reportedholds the first reportedvalue,accession_numberandfiled_date(the same as the served value when nothing was restated).form,filed_date,accession_numberandevidence_urlalways describe the filing the served value came from.
When the latest filing repeats the same number, is_restated stays false, and the served value points to that latest filing. Apple's fiscal 2024 revenue, for example, appears both in its fiscal 2024 10-K and as a comparative in its fiscal 2025 10-K.
What "as filed" means
- Values are what the registrant reported in XBRL. We don't estimate, scale, correct or reconcile them, and we don't fill gaps.
- XBRL tagging errors in a filing are passed through. When a number looks wrong, open
evidence_urland compare it with the financial statements in the filing. - Periods older than a company's first XBRL filing are not covered, even when a later filing repeats them as comparatives.
- The data is refreshed nightly from the SEC's EDGAR bulk archives, which the SEC says are "updated and republished nightly at approximately 3:00 a.m. ET." A filing made today usually appears after the next nightly load;
meta.datasets[].freshnessturnsstaleif a load is more than three days old. - Not included: full-text search of filings, real-time filing streams, insider trading (Forms 3, 4 and 5), ownership and analyst estimates.
Data from SEC EDGAR. Olympus is not affiliated with or endorsed by the U.S. Securities and Exchange Commission.
Sources
- U.S. Securities and Exchange Commission: EDGAR Application Programming Interfaces (APIs)
- U.S. Securities and Exchange Commission: Accessing EDGAR Data