01 · SETUP
Install the library and set your API key
You’ll need Python 3.10 or newer. Save earnings_kpi_watchlist.py in your working folder, then install the libraries:
python -m pip install requestsLog in to get your API key. In the dashboard, click Create API key → Create key → Copy, then return here and replace YOUR_API_KEY below.
$env:VIZUALSTOCKS_API_KEY = "YOUR_API_KEY"export VIZUALSTOCKS_API_KEY="YOUR_API_KEY"Choose the command for your terminal. The key is sent in the X-API-Key header and is not saved in your research export.
02 · DISCOVER
Find the KPIs available in each latest earnings snapshot
python earnings_kpi_watchlist.py --discover PLTR
python earnings_kpi_watchlist.py --discover ADBEDiscovery combines the company KPI catalog with Latest Earnings. It prints each metric’s exact ID, name, format and whether a value appears in the latest returned period. A catalog entry does not guarantee that the newest report includes that metric.
The snapshot request is GET /v1/companies/{ticker}/earnings/latest. It returns one latest reported period for that company, not a list of upcoming earnings dates.
Our watchlist follows Palantir’s customer count and net dollar retention, plus Adobe’s total annual recurring revenue at current exchange rates. The IDs are company-specific: one generic “ARR” field cannot stand in for every issuer’s definition or reporting basis.
The latest snapshot can also contain financial statements and segment figures. This example deliberately selects operating KPIs from the catalog, so the output stays focused on your research questions.
03 · BASELINE
Create a local earnings KPI watchlist
python earnings_kpi_watchlist.py --watch PLTR:customerCount,netDollarRetention --watch ADBE:totalAdobeAnnualRecurringRevenueAtCurrentExchangeRates --output-dir earnings-run-01This creates a new folder with three files: watchlist.csv holds the selected KPI values and fiscal metadata; changes.csv holds differences; snapshot.json is the machine-readable baseline for your next run.
The first run reports baseline, not “new earnings.” You have just observed the current snapshot, which could be weeks old. An empty changes file with a header is expected because there is no earlier local observation to compare.
Values keep their API units. For example, a retention value of 157 means 157%, not 1.57%. Monetary values use the returned reporting currency. Null or absent fields become blank CSV cells with not_returned availability—not zero.
04 · REFRESH
Detect newly reported periods and updated KPI values
python earnings_kpi_watchlist.py --watch PLTR:customerCount,netDollarRetention --watch ADBE:totalAdobeAnnualRecurringRevenueAtCurrentExchangeRates --previous earnings-run-01/snapshot.json --output-dir earnings-run-02Use exactly the same ticker and metric selections, point --previous at the last successful snapshot, and choose a new output folder. If you rerun immediately and the API data has not changed, the result should be unchanged.
- reporting_period_changed
- The latest period label differs from your previous snapshot. Inspect both periods; this is a reporting-period change, not a calculated quarter-over-quarter growth rate.
- value_updated_same_period
- A selected value changed while the period stayed the same. Treat it as an update to investigate, not automatically as a new earnings announcement.
- value_became_available / value_no_longer_returned
- A field changed between missing and numeric. The script records the transition without converting missing data into zero.
- reporting_basis_changed
- Fiscal metadata, currency or value format changed. Review the basis before comparing amounts.
Each company carries its own normalized period, fiscal year, fiscal quarter and period-end date. Adobe and Palantir do not need to share the same latest quarter. Do not join their rows on collection date and call that a matched fiscal period.
05 · REVIEW
Review watchlist updates in Python or Excel
Open the CSV files in Excel, or inspect the change report using Python’s standard library:
import csv
import json
from pathlib import Path
folder = Path("earnings-run-02")
snapshot = json.loads((folder / "snapshot.json").read_text(encoding="utf-8"))
print(snapshot["status"], snapshot["retrievedAtUtc"])
with (folder / "changes.csv").open(encoding="utf-8-sig", newline="") as file:
for row in csv.DictReader(file):
print(row["ticker"], row["metricId"], row["changeType"],
row["previousValue"], "->", row["currentValue"])The report includes previous and current periods, currencies and values. It does not subtract unlike periods or silently aggregate company KPIs. Keep the JSON with your export: its retrieval timestamp records when you checked, not when the issuer published its earnings.
For a different watchlist, run discovery for each new ticker and start a new baseline without --previous. To study a KPI’s full quarterly history, use the company KPI research workbook tutorial instead of treating latest snapshots as a historical database.
06 · REPEAT
Keep the latest snapshot separate from an earnings calendar
An earnings calendar tells you when a report is expected. This workflow checks the latest data available from the API after ingestion. It is neither a calendar feed nor a webhook, and it does not promise immediate availability at the moment a release is published.
The script makes one pass and exits. You can rerun it when reviewing earnings, or later put the command in your own scheduler. Respect your request limits and avoid overlapping runs. Only promote a run’s snapshot.json to your next baseline after the command finishes successfully.
The endpoint returns the latest snapshot, not every release since your last check. If several periods pass between runs, intermediate reports will not be recovered here. Likewise, a temporary change that occurs and reverses between checks will not appear in your local comparison.
07 · TROUBLESHOOTING
Handle missing KPIs and failed requests explicitly
- A KPI is missing from the newest period
- Discovery shows whether it is returned now. A missing value does not prove the company stopped reporting the metric; coverage or ingestion can differ.
- One company returns an error
- The run stops before writing a successful baseline. Resolve the failing company’s access or response rather than treating a partial watchlist as unchanged.
- Previous selection does not match
- Keep the same ticker/metric selections, or start a new baseline. The script rejects incompatible or incomplete snapshots.
- 401, 403 or 429
- Check key access and quota. The script retries temporary GET failures with backoff and Retry-After support. See errors and rate limits.
- Output folder already exists
- Choose another folder. Existing exports are never overwritten, including files left by an interrupted run.
API references: Latest Earnings · Company Metric Catalog · All Company Metrics.
