The stockrow API

Up to ten years of financial statements, metrics and ratios, daily prices, dividends, insider trades and screens for US-listed companies — the figures on stockrow.com — as JSON or as CSV a spreadsheet can read directly. It is read-only, and part of Powerpack.

Get your API key Part of Powerpack. Your keys are on your account page.

Using a spreadsheet? Google Sheets & Excel recipes are copy-and-paste. Using Claude, ChatGPT or Cursor? Connect the MCP server.

Quick start

curl -H "Authorization: Bearer $STOCKROW_KEY" \
  https://stockrow.com/api/v1/companies/AAPL/statements/income-statement.csv?period=annual
code,label,unit,2025-09-27,2024-09-28,2023-09-30,…
REVENUE,Revenue,cash,416161000000,391035000000,383285000000,…
NETINC,Net Income,cash,112010000000,93736000000,96995000000,…

Authentication

Make a key on your account’s API page. Send it as a header, Authorization: Bearer sr_live_…, or — where a header cannot be sent, as in Google Sheets’ IMPORTDATA — as the key parameter: ?key=sr_live_…. A key can read your data feed, your watchlist and your saved screens, and nothing else: never your account, your billing or your email. If one is shared by mistake, roll it on the API page and the old one stops at once.

Every request checks the key’s account. If Powerpack lapses, requests answer 402 until it is renewed, and then the same key works again; keys are never deleted with a subscription.

Formats and units

End a path with .json or .csv; with neither, the answer is JSON unless the request asks for text/csv. JSON is {"data": …, "meta": …}, where meta says where the figures come from, the page on stockrow.com with the same figures (url) and how current they are (as_of). CSV is UTF-8 with a header row.

  • Cash is in US dollars as raw figures — not thousands, not millions.
  • Percentages and growth rates are fractions: 0.05 is 5%.
  • Booleans are 1 or 0. A missing value is null, an empty cell in CSV.
  • Dates are YYYY-MM-DD. Periods run newest first unless you ask for order=asc.
  • Statements go back up to ten years, annual, quarterly and trailing twelve months.
  • Tickers are accepted in any case, BRK.B included.

Errors

Anything that is not a success is JSON {"error": {"code", "message", "docs"}} — or, for a CSV request, two lines, error,message and the two values.

StatusCodeMeans
400invalid_parameterA parameter is missing or out of range; the message names it.
401missing_key, invalid_keyNo key, or one that was revoked or rolled.
402subscription_requiredThe key’s account has no active Powerpack.
404not_foundNo such ticker, metric, statement or screen of yours.
406unsupported_formatA suffix other than .json or .csv.
429rate_limitedOver the limits below; Retry-After says when to try again.
500internalOur fault; it is logged.

Limits

60 requests a minute and 5,000 a day for each key, the API and the MCP server together. Every response says what is left: RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds) for the minute, and X-RateLimit-Remaining-Day. A spreadsheet of fifty formulas refreshing every hour uses about 1,200 a day. To fetch many companies at once, use /metrics/latest: up to 100 tickers and 25 metrics in one request. /status shows a key’s allowance without costing much of it.

Statements and the latest-values grid send an ETag; send it back as If-None-Match and an unchanged answer is a 304 with no body.

Versioning

/api/v1 only grows: new fields, new CSV columns added on the right, new endpoints. A field is never renamed, removed or reordered, and a unit or a code never changes. A change that would break that is /api/v2, and v1 then keeps working for at least twelve months, with Deprecation and Sunset headers and an email to everyone with an active key.

Reference

Base URL https://stockrow.com/api/v1. The same reference as OpenAPI 3.1: openapi.yaml.

Companies

GET /companies/search — Find companies by ticker or name

ParameterInTakesNotes
q (required) query string A ticker or part of a company's name.
limit query 1 to 20 — default 10

GET /companies/{ticker}/profile — A company's name, exchange, sector and industry, with its latest price and market cap

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).

GET /companies/{ticker}/statements/{statement} — One financial statement, up to ten years

Wide by default: a row per line item with its stable code, label and unit, then a column per period end, newest first (column D in a spreadsheet is always the latest period). layout=long is a row per cell instead.

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).
statement (required) path income-statement, balance-sheet, cash-flow, metrics-ratios
period query annual, quarterly, ttm — default annual The balance sheet has no ttm.
limit query 1 to 40 Periods; 10 by default for annual, 12 otherwise.
order query desc, asc — default desc
layout query wide, long — default wide

GET /companies/{ticker}/prices — Daily open, high, low, close and volume, newest first

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).
from query date
to query date

GET /companies/{ticker}/dividends — Dividends over the last ten years, newest first

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).
limit query 1 to 200

GET /companies/{ticker}/insider-transactions — Insider buys and sells, newest first

value is the trade in dollars, owned_after the shares the insider holds after it.

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).
type query buy, sell
limit query 1 to 200 — default 50

Metrics

GET /companies/{ticker}/metrics/{slug} — One metric's history for a company

slug is a metric slug such as pe-ratio, revenue or free-cash-flow, or any indicator's lower-cased code; /indicators lists them.

ParameterInTakesNotes
ticker (required) path string The ticker, in any case (aapl, BRK.B).
slug (required) path string
period query annual, quarterly, ttm, daily, latest Defaults to the metric's own; only the periods it comes in are accepted.
limit query 1 to 120
from query date
to query date

GET /metrics/latest — The latest value of up to 25 metrics for up to 100 companies, as one grid

A row per ticker in the order asked for. A ticker stockrow does not cover gets a row of empty cells rather than an error, and is named in meta.unknown_tickers.

ParameterInTakesNotes
tickers (required) query string Comma-separated, at most 100.
metrics (required) query string Comma-separated metric slugs, at most 25.

Your account

GET /watchlist — The companies you follow, with the day's price and change

ParameterInTakesNotes
metrics query string Optional comma-separated metric slugs to add as columns, at most 25.

GET /screens — Your saved screens

GET /screens/{id}/results — The companies one of your saved screens matches today, with its columns

ParameterInTakesNotes
id (required) path uuid
limit query 1 to 1000 — default 500
offset query integer — default 0

Reference

GET /indicators — The data dictionary — every metric and line item, with its slug, unit, periods and meaning

ParameterInTakesNotes
tier query core, advanced
q query string

GET /status — Your key, your plan, and the requests you have left