Python SDK Guide
Install valuein-sdk, set your API key, and run your first DuckDB query against 105M+ SEC EDGAR facts in under 60 seconds.
No token required to start. WithoutVALUEIN_API_KEYthe SDK falls back to the SAMPLE dataset (S&P 500, last 5 years). Same code runs against your full plan once you add a key.
Install
Install in any virtual environment — pip and uv both ship the same SDK. Pick whichever you already use.
# Option A — pip (universal, ships with Python)
python -m venv .venv && source .venv/bin/activate
pip install valuein-sdk
# Option B — uv (10–100× faster; install from https://docs.astral.sh/uv/)
uv venv && source .venv/bin/activate
uv pip install valuein-sdkAuthenticate
API key is OPTIONAL. With no key, the SDK runs in SAMPLE mode (S&P 500, last 5 years). Add a token to unlock the full universe — the code below does not change.
# optional — sample tier works without a key
echo 'VALUEIN_API_KEY="your_api_key"' >> .envFirst Query
Define your SQL, open a client context, run client.run_query() — returns a pandas DataFrame
from valuein_sdk import ValueinClient, ValueinError
sql = """
SELECT
r.symbol,
r.name,
f.fiscal_year,
MAX(CASE WHEN standard_concept = 'Revenues' THEN numeric_value END) AS revenue,
MAX(CASE WHEN standard_concept = 'NetIncomeLoss' THEN numeric_value END) AS net_income,
MAX(CASE WHEN standard_concept = 'EarningsPerShareDiluted' THEN numeric_value END) AS eps_diluted
FROM fact f
JOIN references r ON f.entity_id = r.cik
WHERE f.form_type = '10-K'
AND r.symbol = 'AAPL'
GROUP BY r.symbol, r.name, f.fiscal_year
ORDER BY f.fiscal_year DESC
LIMIT 10
"""
try:
with ValueinClient() as client:
df = client.run_query(sql)
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Client Methods
All available client methods — check connection, inspect your plan, list tables, download full tables, and run named templates
from valuein_sdk import ValueinClient, ValueinError
try:
with ValueinClient() as client:
# Connection check — no API key required
print(client.health()) # {"ok": true, "latency_ms": 42}
# Your account details
print(client.me()) # {"plan": "growth", "status": "active", "email": "...", "createdAt": "..."}
# Dataset snapshot metadata
print(client.manifest()) # {"snapshot": "2026-03-26", "last_updated": "...", "tables": [...]}
# List available table names
print(client.tables()) # ["entity", "security", "filing", "fact", "valuation", "references", ...]
# Download a full table as a DataFrame (no SQL needed)
filing_df = client.get(table="filing")
print(filing_df.head())
# Run a named SQL template — kwargs only, raw values (the SDK quotes them safely)
df = client.run_template("fundamentals_by_ticker", ticker="AAPL")
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Point-in-Time
Filter by accepted_at to reconstruct exactly what was known on any historical date — no look-ahead bias in your backtests
from valuein_sdk import ValueinClient, ValueinError
# What did investors KNOW about AAPL's FY2022 revenue as of Jan 1, 2023?
# Excludes any restatements or 10-K/A amendments filed after that date.
sql = """
SELECT
r.symbol,
f.fiscal_year,
f.period_end,
f.accepted_at,
MAX(CASE WHEN standard_concept = 'Revenues' THEN numeric_value END) AS revenue,
MAX(CASE WHEN standard_concept = 'NetIncomeLoss' THEN numeric_value END) AS net_income
FROM fact f
JOIN references r ON f.entity_id = r.cik
WHERE f.form_type = '10-K'
AND r.symbol = 'AAPL'
AND f.accepted_at <= '2023-01-01' -- Only facts known by this date
GROUP BY r.symbol, f.fiscal_year, f.period_end, f.accepted_at
ORDER BY f.fiscal_year DESC
LIMIT 10
"""
try:
with ValueinClient() as client:
df = client.run_query(sql)
print(df[["fiscal_year", "period_end", "accepted_at", "revenue", "net_income"]])
except ValueinError as e:
print(f"Valuein error: {e}")Screener
Screen the S&P500 with a single pivot query — one pass over the fact table, no self-joins
from valuein_sdk import ValueinClient, ValueinError
# S&P500 companies with ROE > 20% and Debt/Equity < 1.0 in the latest fiscal year.
# Membership is resolved via index_membership (the references table has no
# is_sp500 flag — that snapshot column was dropped 2026-05-02).
sql = """
SELECT
r.symbol,
r.name,
r.sector,
ROUND(
MAX(CASE WHEN standard_concept = 'NetIncomeLoss' THEN numeric_value END) /
NULLIF(MAX(CASE WHEN standard_concept = 'StockholdersEquity' THEN numeric_value END), 0),
3
) AS roe,
ROUND(
MAX(CASE WHEN standard_concept = 'LongTermDebt' THEN numeric_value END) /
NULLIF(MAX(CASE WHEN standard_concept = 'StockholdersEquity' THEN numeric_value END), 0),
3
) AS debt_to_equity,
MAX(CASE WHEN standard_concept = 'EarningsPerShareDiluted' THEN numeric_value END) AS eps_diluted
FROM fact f
JOIN references r ON f.entity_id = r.cik
JOIN index_membership im ON im.cik = r.cik
WHERE f.form_type = '10-K'
AND f.fiscal_year = 2024
AND im.index_name = 'SP500'
AND im.removal_date IS NULL
AND r.is_active = TRUE
GROUP BY r.symbol, r.name, r.sector
HAVING roe > 0.20 AND debt_to_equity < 1.0
ORDER BY roe DESC
LIMIT 20
"""
try:
with ValueinClient() as client:
df = client.run_query(sql)
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Error Handling
Catch ValueinError to handle all SDK exceptions — authentication failures, rate limits, and network errors in one place
from valuein_sdk import ValueinClient, ValueinError
sql = "SELECT COUNT(*) AS total_facts FROM fact"
try:
with ValueinClient() as client:
df = client.run_query(sql)
print(df)
except ValueinError as e:
# ValueinError covers all SDK exceptions:
# - missing or invalid VALUEIN_API_KEY
# - rate limit exceeded for your plan tier
# - network or connection failures
# - malformed SQL or query execution errors
print(f"Valuein error: {e}")Quick Reference
All client methods at a glance.
| Method | Returns | Description |
|---|---|---|
client.health() | dict | Connection status check. No API key required. |
client.me() | dict | Your plan, status, email, and account creation date. |
client.manifest() | dict | Snapshot date, last_updated timestamp, and available tables. |
client.tables() | list[str] | Names of all tables loaded in the current session. |
client.run_query(sql) | DataFrame | Execute any DuckDB SQL query → pandas DataFrame. |
client.get(table=...) | DataFrame | Download a full table as a pandas DataFrame. No SQL needed. |
client.run_template(name, params) | DataFrame | Run a named SQL template with positional parameters. |
Ready to pull real data?
Generate your API key and run these examples against live SEC EDGAR data. Free tier includes 100 API calls/day — no credit card required.