Financial statements on Massive are four separate endpoints under /stocks/financials/v1/, not one, and each returns a flat record with named columns rather than a nested structure you have to walk. Decide which statement you need before you write the request, because there is no call that returns all four.
Applies to
- Plans: Stocks Advanced, or any plan carrying the Financials and Ratios Expansion. Basic, Starter, Developer and plain Business do not include it. Data is end-of-day, and the oldest record covers a period ending in April 2009.
- Endpoints: /stocks/financials/v1/income-statements, /stocks/financials/v1/balance-sheets, /stocks/financials/v1/cash-flow-statements, /stocks/financials/v1/ratios.
- Asset classes: US stocks.
What one record looks like
Each record is flat: the metadata columns, then the line items as named numbers.
curl -X GET "https://api.massive.com/stocks/financials/v1/income-statements?tickers=AAPL&sort=period_end.desc&limit=1&apiKey=YOUR_API_KEY"
Response
{
"status": "OK",
"results": [
{
"tickers": ["AAPL"],
"cik": "0000320193",
"period_end": "2026-06-27",
"filing_date": "2026-07-31",
"fiscal_quarter": 3,
"fiscal_year": 2026,
"timeframe": "trailing_twelve_months",
"revenue": 466823000000.0,
"cost_of_revenue": 239700000000.0,
"gross_profit": 227123000000.0,
"operating_income": 154859000000.0,
"ebitda": 167959000000.0
}
]
}
The five metadata columns are on every record of all four endpoints. timeframe is quarterly, annual or trailing_twelve_months, and one ticker carries all three interleaved: of AAPL's 147 income statement records, 67 are quarterly, 64 trailing twelve month and 16 annual. Filter on timeframe or you will be comparing a quarter with a year.
How many fields each endpoint returns
The counts below are what AAPL's most recent record carried on each endpoint, so they are the full column set rather than a subset:
| Endpoint | Fields | Examples beyond the metadata |
|---|---|---|
| income-statements | 34 | revenue, gross_profit, operating_income, basic_earnings_per_share, ebitda |
| balance-sheets | 40 | total_assets, total_current_liabilities, retained_earnings_deficit, total_equity |
| cash-flow-statements | 34 | net_cash_from_operating_activities, purchase_of_property_plant_and_equipment, dividends |
| ratios | 23 | price_to_earnings, return_on_equity, debt_to_equity, enterprise_value, free_cash_flow |
Two things to know before you build a fixed-width table out of this. Within one era a concept the company did not report comes back as 0.0 rather than absent, so a zero is not automatically a filed zero. Across eras the column set itself moves: AAPL's 147 income statement records carry 26, 28 or 34 fields, and the oldest ones have no interest_expense, interest_income, depreciation_depletion_amortization, discontinued_operations, equity_in_affiliates, extraordinary_items, noncontrolling_interest or preferred_stock_dividends_declared at all. Read the keys that are there rather than indexing a fixed list.
The filter parameter is not the same on all four
Read this before you debug an unfiltered response. The three statement endpoints filter on tickers, plural, because a record can cover several symbols. ratios filters on ticker, singular. Passing the wrong one is not an error: it is ignored, the request succeeds, and you get whatever the default sort returns, which is a different company entirely.
curl -X GET "https://api.massive.com/stocks/financials/v1/ratios?ticker=AAPL&limit=1&apiKey=YOUR_API_KEY"
Response
{
"status": "OK",
"results": [
{ "ticker": "AAPL", "cik": "0000320193", "date": "2026-09-10", "price": 326.57,
"market_cap": 4766021362600.0, "earnings_per_share": 8.83, "price_to_earnings": 36.97,
"return_on_equity": 1.1991, "debt_to_equity": 0.78, "free_cash_flow": 136683000000.0 }
]
}
ratios is the odd one out in two more ways. It carries a date, the day the ratios were computed from that day's price, rather than a period_end. And it holds no history at all: one record per ticker, the latest, and date is not among the columns sort accepts.
The three statement endpoints also cover currently active companies only. A request for a delisted ticker returns an empty results array rather than its final filings, so this is not the place to research a company that no longer trades.
The older nested endpoint no longer returns data
Code written before these endpoints existed calls /vX/reference/financials, which was deprecated on 20 September 2025 and listed as sunset on 22 June 2026. Its Sunset response header gives 9 October 2026, and a request to it now returns HTTP 410 with no results, plus a Link header naming the new documentation:
curl -i -X GET "https://api.massive.com/vX/reference/financials?ticker=AAPL&apiKey=YOUR_API_KEY"
Response
HTTP/2 410
deprecation: true
sunset: 2026-10-09
link: <https://massive.com/docs/rest/stocks/fundamentals/balance-sheets>; rel="successor-version"
{"status":"GONE","error":"This endpoint has been deprecated and is undergoing a brownout. Please check the Sunset and Link response headers for migration details."}
The body says "brownout", but the Sunset date has passed, so treat the 410 as permanent and move to the /stocks/financials/v1/ endpoints.
Where each /vX/reference/financials field went
The old /vX/reference/financials record held the income statement, balance sheet, cash flow statement and comprehensive income nested under a financials object, each line item an object with value, unit, label and order. Its record-level fields map to the new endpoints like this:
| Old field | New endpoint | New field |
|---|---|---|
| cik, tickers, fiscal_year | Income statements, balance sheets, cash flow statements | The same names |
| filing_date | The three statement endpoints | filing_date, the most recent filing that included the period |
| end_date | The three statement endpoints | period_end |
| fiscal_period | The three statement endpoints | fiscal_quarter, read with timeframe |
| timeframe | The three statement endpoints | timeframe, with trailing_twelve_months in place of ttm |
| financials.income_statement | /stocks/financials/v1/income-statements | One named column per line item |
| financials.balance_sheet | /stocks/financials/v1/balance-sheets | One named column per line item |
| financials.cash_flow_statement | /stocks/financials/v1/cash-flow-statements | One named column per line item |
| source_filing_url, source_filing_file_url | SEC EDGAR Index, /stocks/filings/vX/index | filing_url |
| company_name | SEC EDGAR Index, or Ticker Overview at /v3/reference/tickers/{ticker} | issuer_name, or name |
| sic | Ticker Overview at /v3/reference/tickers/{ticker} | sic_code |
| start_date | No successor | Records carry period_end only |
| acceptance_datetime | No successor | The SEC EDGAR Index gives the filing_date only |
| financials.comprehensive_income | No successor | Balance sheets carry accumulated_other_comprehensive_income, a running balance rather than the period's comprehensive income |
Line items on the new endpoints are plain numbers, and many were renamed. The headline items moved to these columns:
| Old line item | New endpoint | New field |
|---|---|---|
| income_statement.revenues | Income statements | revenue |
| income_statement.operating_income_loss | Income statements | operating_income |
| income_statement.basic_earnings_per_share, diluted_earnings_per_share | Income statements | The same names |
| income_statement.basic_average_shares, diluted_average_shares | Income statements | basic_shares_outstanding, diluted_shares_outstanding |
| balance_sheet.assets, liabilities, equity | Balance sheets | total_assets, total_liabilities, total_equity |
| balance_sheet.current_assets, current_liabilities | Balance sheets | total_current_assets, total_current_liabilities |
| cash_flow_statement.net_cash_flow_from_operating_activities, and the investing and financing equivalents | Cash flow statements | net_cash_from_operating_activities, net_cash_from_investing_activities, net_cash_from_financing_activities |
| cash_flow_statement.net_cash_flow | Cash flow statements | change_in_cash_and_equivalents |
Match any other line item by the field descriptions on the income statements, balance sheets and cash flow statements pages, not by name. Before you compare new values with figures you stored, note that each new record carries the figures from the most recent filing that included the period, and that share counts and earnings per share are restated for later splits, as Are Massive's fundamentals adjusted for stock splits? explains. Treat a migration as a rewrite of the parsing layer, not a change of URL.
If you see an error
A response full of the wrong company means the filter parameter was ignored. Check tickers against ticker for the endpoint you are calling.
A 400 on sort means the column is not sortable on that endpoint, and the error names every column that is. The statements sort on period_end; ratios does not accept date.
An HTTP 410 with "status":"GONE" comes from the retired /vX/reference/financials endpoint. Move to the three statement endpoints, using the field map in the previous section.
An empty results array for a company you know filed is usually a delisting. Only active companies are covered.
A NOT_AUTHORIZED response means the plan does not carry financials. It is an Advanced or Expansion feature, not part of the reference data every plan gets.

