API Documentation
One endpoint, one promise: ask what was knowable about a company on a date, and that's exactly — and only — what you get back.
Machine-readable: OpenAPI 3.1 spec — /openapi.json · live check: /status
Authentication
Send your API key with every request, either way:
x-api-key: tvd_your_key_here # or Authorization: Bearer tvd_your_key_here
Evaluation keys are issued after card-backed checkout on the pricing page; keys are deactivated when access ends. One key per person — don't share it. Limits depend on the plan (evaluation: 100 requests/day, 10 companies total, rolling 3-year history; Pro: 5,000 requests + 2,500 distinct tickers/day) — see Limits.
GET/v1/fundamentals
Returns, for each concept, the most recent fiscal period whose source filing had been filed on or before as_of — the point-in-time view. Note the boundary is inclusive: a 10-K filed on as_of itself counts as knowable that day (filings often land after market close — use the prior day if you need strict before-the-open semantics).
Query parameters
Share classes and other aliases resolve to the SEC filer they belong to — GOOG → GOOGL, BRK-A → BRK-B, and roughly 1,500 more (preferred-share tickers like BAC-PK → BAC, renamed issuers, OTC duplicates of a listed filer). When that happens the response echoes the ticker you sent and adds resolved_ticker plus a resolved_note explaining that fundamentals are reported at the filer level. Both fields are absent when no alias was involved.
Response fields
Example
curl "https://tradevodata.com/v1/fundamentals?ticker=AAPL&as_of=2024-06-30&concept=Revenue" \ -H "x-api-key: tvd_your_key_here"
{
"ticker": "AAPL",
"as_of": "2024-06-30",
"period": "annual",
"data_through": "2026-07-24",
"count": 1,
"fundamentals": [{
"concept": "Revenue",
"fiscal_year": 2023,
"fiscal_period": "FY",
"period_end": "2023-09-30",
"period_start": null,
"filed": "2023-11-03",
"lag_days": 34,
"value": 383285000000,
"latest_value": 383285000000,
"ytd_value": null,
"derivation": "reported",
"source_form": "10-K",
"restated": false,
"qa_status": "clean"
}]
}Note the answer is FY2023, not FY2024 — on 2024-06-30 the FY2024 10-K had not been filed yet. That is the whole product.
curl "https://tradevodata.com/v1/fundamentals?ticker=AAPL&as_of=2025-02-15&period=quarterly" \ -H "x-api-key: tvd_your_key_here"
Quarterly rows keep the same point-in-time rule and label reported versus derived values. Omit period to preserve the annual default.
The data_through value above is illustrative — it advances with every data load. Read the live one from any response, or check /status.
Python
The official client. as_of is a required argument on every query — there is no way to ask it for “Apple's revenue”, only for what was knowable on a given date, which is how lookahead bias stops being something you can write by accident. Zero dependencies; pandas is optional.
Quarterly client support ships in version 0.2.0. A fresh install gets the current release; upgrade first if this package is already installed in the environment.
pip install tradevodata # Existing environment: pip install --upgrade tradevodata
import tradevodata as tv
df = tv.sample() # 5-company proof pack — no API key needed
client = tv.Client(api_key="tvd_...") # or set TRADEVODATA_API_KEY
client.fundamentals("AAPL", as_of="2024-06-30") # -> FY2023; annual default
client.fundamentals("AAPL", as_of="2025-02-15", period="quarterly")
client.snapshot(as_of="2024-06-30", concept="Revenue", to_pandas=True)Source: github.com/christianpichichero-max/tradevodata-py · PyPI
Note: as of June 2024, the newest knowable Apple annual revenue is FY2023 — FY2024 wasn't filed until 2024-11-01. That's the product.
Python (plain requests)
import requests
r = requests.get(
"https://tradevodata.com/v1/fundamentals",
params={"ticker": "AAPL", "as_of": "2024-06-30"},
headers={"x-api-key": "tvd_your_key_here"},
)
for f in r.json()["fundamentals"]:
print(f["concept"], f["value"], "known since", f["filed"])R
library(httr)
r <- GET(
"https://tradevodata.com/v1/fundamentals",
query = list(ticker = "AAPL", as_of = "2024-06-30"),
add_headers(`x-api-key` = "tvd_your_key_here")
)
for (f in content(r)$fundamentals) {
cat(f$concept, f$value, "known since", f$filed, "\n")
}Errors
An empty result with count: 0 and a note means the ticker exists but nothing had been filed on or before your as_of.
GET/v1/health
Public liveness check (no key needed): returns { ok, rows, published_rows, stale_build, quarterly_rows, published_quarterly_rows, stale_build_quarterly, quarterly_public, db_ms }.
Responses are edge-cached for 60 seconds, so the count is at most a minute old.
Limits
Daily limits per key, by plan. All reset at 00:00 UTC, and every 429 carries a Retry-After header with the seconds until reset.
The honest why: the dataset is the product. A real backtest touches a few hundred names; a full-universe scrape is all 5,168. The ticker cap sits between those two on purpose — it's an anti-bulk-extraction wall, not a revenue lever. For whole-universe work, don't fight the cap — use the bulk endpoints below (paid plan).
Bulk & cross-section
For whole-universe work — cross-sectional screens, factor backtests — don't loop the per-ticker endpoint. Both are Pro-only endpoints ($29/mo after the evaluation); an evaluation key gets a 403 here, un-metered.
curl -H "x-api-key: tvd_..." "https://tradevodata.com/v1/download?period=quarterly" -o tradevodata-quarterly.csv.gz curl -H "x-api-key: tvd_..." "https://tradevodata.com/v1/snapshot?as_of=2025-02-15&period=quarterly&concept=Revenue"
Coverage & semantics
- 5,168 US companies · 632,466 point-in-time rows · 16 concepts · up to 12 fiscal years.
- Annual 10-K/10-K/A plus quarterly 10-Q history (SEC EDGAR XBRL). Q4 is reported where tagged or derived and labelled where supported; Q4 EPS and diluted shares are not derived.
- filed is the earliest filing that reported the value — across synonym XBRL tags, so re-tagged values keep their true first-public date.
- Support: email us. Manage billing at /account.
Inspect the proof before you need a key.
The public proof pack covers 5 companies and 3 fiscal years with the same fields — no signup.
Or run the 3-minute Colab — nothing to install.