SEC Filings API Reference
SEC financial statements with a data-quality signal in
every response. Each balance sheet comes with a check: whether
it reconciles to A = L + E, whether the lines we served are complete, and,
when it does not add up, whether the gap is in the filing or in what we
read. A filing that does not report the lines needed is marked not
testable instead of passing. Filed figures only: nothing here is derived,
scored or predicted.
Try it without a key
100 an hour from any one address, no registration.
macOS and Linux:
curl -sS https://balanceproof.dev/api/demo/JPM
Windows PowerShell, where curl is an
alias for Invoke-WebRequest and will not take those
flags:
curl.exe -sS https://balanceproof.dev/api/demo/JPM
Or PowerShell's own client, which parses the response instead of printing it:
Invoke-RestMethod https://balanceproof.dev/api/demo/JPM
What the check says
Every /api/company/{ticker} and
/api/demo/{ticker} response carries a check
object next to the figures. An excerpt:
"check": {
"identity_status": "missing_tag",
"reconciles": false,
"filer_totals_agree": true,
"attribution": "extraction",
"components_complete": false,
"imbalance_pct": 34.054,
"missing_for_check": [],
"note": "The filer's own totals agree. The liability and equity lines served here fall short of its stated total by imbalance_pct of total assets: a line this dataset did not read. Use the stated totals."
}
attribution | Means |
|---|---|
none | It reconciles: assets equal liabilities plus equity. |
extraction | The filer's own totals agree; a line did not reach this dataset. Use the stated totals, not the components. |
filer | The filing's own stated total differs from its total assets (under 1% is reported as rounding). |
unknown | It does not add up and the filing states no total to check against. |
null | Not testable: the filing does not report the lines the check needs. reconciles is null too, never a pass. |
The same verdict is returned by the MCP tool
check_balance_sheet and, for many tickers at once, by
POST /api/verify. How it is computed:
how we verify.
Getting a key
A key is issued the moment you give an address. The free tier needs no payment and no card. It is not a trial that stops.
Authentication
Send the key in an X-API-Key header, or as
Authorization: Bearer YOUR_KEY (the form the MCP server
takes). It does not expire, and there is no OAuth dance.
Treat it like a password: anyone holding it can spend your calls. Your
key is stored as a hash. The full value is shown once at issue;
regenerate from the dashboard if lost.
curl -H "X-API-Key: YOUR_KEY" \
https://balanceproof.dev/api/company/JPM
On Windows PowerShell, use curl.exe and
keep the command on one line: plain curl there is
Invoke-WebRequest, and the backslash is not a line break.
curl.exe -H "X-API-Key: YOUR_KEY" https://balanceproof.dev/api/company/JPM
Lost it? Sign in. The dashboard shows the first eight characters, so you can tell which key an account is holding, and a Regenerate button that issues a new one. The old key stops working the moment you press it.
Python
The official client wraps every endpoint below. It needs
nothing beyond the standard library; pandas is only for
panel(), which returns one row per company and period,
ready for a backtest.
pip install "balanceproof[pandas]"
import balanceproof as bp
client = bp.Client("YOUR_KEY") # or set BALANCEPROOF_API_KEY
client.check("CELH")["attribution"] # "none" | "filer" | "extraction" | "unknown"
client.statements("AAPL", period="quarterly")
client.balance_sheet("AAPL", as_of="2025-03-01") # Pro and above
df = client.panel(["AAPL", "MSFT"], ["revenue", "net_income"])
On PyPI. A call your plan does not include raises
balanceproof.PlanRequired, naming the plan that does.
What the balance sheet endpoint returns, with a real response: XBRL balance sheet API.
Choosing between providers? The four tests worth running on any of them, this one included: SEC filings API for quants and balance sheet API.
Endpoints
/api/company/{ticker}
X-API-Key required · counts as one call
The balance sheet as filed: every line item, its period end, and the filing it came from. The same numbers the drawing on /company/{ticker} is built from. Add ?as_of=YYYY-MM-DD (Pro and above) for the balance sheet exactly as it was public that day: only filings made by then, the original figure before a restatement and the revision after. What filing_date means: on a line item it is the filing that first reported that value (a later filing that only repeats it, as every 10-Q repeats the prior year end, does not move it; a filing that reports a different value for the same period does); on the sheet itself it is the filing that supplied total assets.
/api/company/{ticker}/history?years=N
X-API-Key required · counts as one call
Every filed balance sheet over past periods, newest first. How far back is the shorter of your plan (Free 1 year, paid plans more) and what is loaded: periods from late 2022 or 2023 for most companies today. available_from in the response says where the data starts.
/api/company/{ticker}/statements?period=annual|quarterly
X-API-Key required · counts as one call · as_of Pro and above
Income statement and cash flow per period. Each period is checked when the filing reports the lines the check needs; where it does not, the check returns not_testable instead of passing. The checks: revenue minus cost of revenue against gross profit, and operating + investing + financing + FX against the change in cash, with the gap when it fails. Q4, and Q2/Q3 cash flow, are worked out from the filed year and year-to-date figures and named in derived. Depth as for history.
/api/exceptions?since=&type=&ticker=&attribution=&format=json|csv
X-API-Key required · Pro (last 90 days) and Business (all) · one call
Every filing whose balance sheet fails the check, with whose problem it is (filer, extraction or unknown), and every figure a later filing restated, across all companies, newest first. A restatement is the same XBRL tag reported again at a new value; a switch between tags that measure different things is not one. format=csv for a download. The last 90 days are free to browse at /restatements.
/api/company/{ticker}/changes
X-API-Key required · Starter and above · one call
What moved since the previous period, figure by figure, and every figure a later filing restated (same XBRL tag, new value): the original value, the revised one, and which filings said each.
/api/verify
X-API-Key required · Pro (50 per request) and Business (500) · one call per ticker
Check many balance sheets at once: body {"tickers": ["AAPL", "JPM"]}. For each: whether Assets = Liabilities + Equity holds, the gap as a percentage of assets, and why it balances when it needed the minority interest. On Business, every result and every balance sheet also carries provenance: the filing it came from, with a link to it on SEC.gov.
/api/watchlist
X-API-Key required · Starter and above · free
Watch a company: body {"ticker": "AAPL"}. When it files, you get one email saying whether the new balance sheet reconciles, what moved, and anything restated. Starter watches 3, Pro 50, Business 500. GET /api/watchlist lists them, DELETE /api/watchlist/{ticker} removes one.
/api/webhooks
X-API-Key required · Business (5 endpoints) · free
Register an https URL: body {"url": "https://..."}. When a watched company files, it receives a watchlist.filed POST with the same facts as the email. Each request carries BalanceProof-Signature: t=..,v1=.., an HMAC-SHA256 of t.body with the secret returned once at creation. POST /api/webhooks/{id}/test sends a signed ping.
/api/plans
Public
What each plan includes, as data: call quotas, history depth, watchlist size and the rest.
/api/demo/{ticker}
No key · 100/hour per address
The same response, so you can see the shape before deciding whether to register. It is the keyed endpoint underneath, so it is metered -- generously, and not per key.
/api/user/status
X-API-Key required · free
Your tier, the calls you have spent this calendar month, and what is left. Checking never costs a call.
/api/download-dataset
X-API-Key required · $79.99 one-off
Every fundamental figure this site holds, streamed as CSV. One purchase, no subscription, re-downloadable whenever you like.
/api.json
Public
This page's machine-readable index: the endpoint list, as JSON.
/health
Public
Whether the service is up and can reach its database. Cheap, and the one to point an uptime monitor at.
Limits
Counted per calendar month and reset on the first, whatever day you registered. A call that fails on our side is not counted.
| Plan | Calls / month | Over the limit |
|---|---|---|
| Free | 1,000 | 429, with the reset date |
| Pro | 10,000 | 429, with the reset date |
An expired Pro subscription falls back to the free allowance. It does not lock you out, and the key does not change.
Responses
JSON on every path, including the errors: a failure never returns an HTML page to something that asked for data.
| Code | Means |
|---|---|
| 200 | Here it is. |
| 401 | No key, or a key that is not ours. |
| 404 | Nothing filed for that ticker. |
| 429 | Month spent, or the demo's hourly cap. |
# what a spent month looks like
curl -sS -o /dev/null -w "%{http_code}\n" \
-H "X-API-Key: YOUR_KEY" https://balanceproof.dev/api/company/AAPL
429
Data is for informational purposes only. Not financial advice.