Hub-Equity Python SDK: programmatic access to XBRL / iXBRL financial data (SEC EDGAR + ESEF Europe) via the public REST API.
Project description
hub-equity: Python SDK
Typed Python client for the Hub-Equity financial-data API: machine-readable XBRL / iXBRL from primary filings, SEC EDGAR (US) and ESEF (Europe), normalized into canonical financial concepts, with the provenance preserved.
What sets the data apart, and what this SDK exposes:
- Source-linked. Every value carries the filing it came from (
form_type,filing_date, a viewer URL). You can trace any number back to the filer's document, not a black box that silently rewrites as-filed history. - Point-in-time. Query a metric as it was known on a date (
get_metric_as_of): filings filed after the cutoff are excluded. No lookahead bias for backtests. - XBRL-native. Calculation linkbase (with filer weights and verifier-corrected weights), dimensional structure, and the raw filer-declared facts, not just flattened labels.
- Restatement-aware. Per-concept deltas across 10-K/A amendments.
- Cross-issuer, calendar-aligned.
comparematches periods by calendar year (Bloomberg / FactSet convention), so Apple (Sep FYE) and a Dec-FYE peer line up.
The SDK is a thin, typed wrapper over the public REST API: it ships no data and no secrets; you bring your own API key. Full API reference: https://docs.hub-equity.com.
Maturity. The data engine and public REST API behind this SDK run in production and power Hub-Equity's own chat. This PyPI package is a newly published client for that API; the surface is stable (SemVer 1.0), but as a distributed package it is fresh, hence the Beta classifier.
Install
pip install hub-equity
# Optional pandas helpers:
pip install 'hub-equity[pandas]'
Python 3.10+. Runtime deps: httpx, pydantic.
Authentication
from hub_equity import HubEquity
# Explicit key
client = HubEquity(api_key="hubq_live_...")
# Or set HUBEQUITY_API_KEY env var (recommended for notebooks)
client = HubEquity()
# Or no key: anonymous freemium access (lower rate limits, premium endpoints gated)
client = HubEquity(api_key="")
Get a key at https://hub-equity.com/settings/api-keys (shown once, store it securely).
Set HUBEQUITY_API_URL to point the client at a non-default host (defaults to
https://api.hub-equity.com).
Entity arguments accept a ticker (e.g. "AAPL") or a Hub-Equity UUID on every
entities/{id}/... method. The one exception is compare, which takes UUIDs only
(resolve a ticker via the entity detail endpoint or the web app first).
Quickstart
from hub_equity import HubEquity
with HubEquity() as client:
rev = client.get_metric_history("AAPL", "REVENUE", years=5)
print(f"{rev.entity_name}: {rev.hub_label} (CAGR {rev.cagr_pct:.1f}%)")
for p in rev.points:
print(f" FY{p.fiscal_year}: {p.value:,.0f} {p.currency}"
f" ({p.yoy_growth_pct:+.1f}% YoY) ← {p.source.form_type} {p.source.filing_date}")
# p.source.viewer_url / p.source.external_url -> trace back to the filing
Methods
| Area | Method | Returns |
|---|---|---|
| Time-series | get_metric_history(entity, code, *, years=5, period_type='FY') |
MetricHistory: values + YoY + CAGR |
| Point-in-time | get_metric_as_of(entity, code, as_of, *, years=5, period_type='FY') |
AsOfResponse: series as known on a date |
| Compare | compare(entity_ids, hub_concept_codes, fiscal_year, fiscal_period_type='FY') |
CompareEntitiesResult: N×M matrix |
| Calc linkbase | get_calculation_sections(filing_id) |
CalculationSectionsResponse: calc roles |
get_calculation_tree(filing_id, link_role) |
CalculationTree: edges + weights |
|
| Dimensions | get_entity_dimensions(entity) |
EntityDimensionsResponse: axes + members |
| Raw facts | get_filing_facts(filing_id, *, section, concept, is_extension, limit, offset) |
RawFactsResponse |
| Restatements | get_restatement_diff(entity, *, fiscal_year, hub_concept_code, min_diff_pct=0.01, kind) |
AmendmentDiffResult |
| Quality | get_filing_quality_grade(filing_id) |
QualityGradeResponse: A-F + 4 drivers |
| Concepts | search_concepts(q, *, taxonomy, category, limit, offset, cursor) |
ConceptSearchResponse |
iter_concepts(q, *, taxonomy, category, page_size=100) |
generator of ConceptSummary |
|
get_concept(hub_concept_code) |
ConceptDetail: forward catalog entry (label, description, category, taxonomy scope) |
Every method returns a typed pydantic model (autocomplete + validation), with
extra="allow" so a newer API never breaks an older SDK.
Point-in-time: no lookahead bias
# What did Apple's FY2022 revenue look like as known on 2023-01-15,
# before any later 10-K/A restated it?
snap = client.get_metric_as_of("AAPL", "REVENUE", as_of="2023-01-15", years=3)
for p in snap.points:
print(f"FY{p.fiscal_year}: {p.value:,.0f} {p.currency}"
f" (from {p.form_type} filed {p.filing_date})")
Compare issuers (calendar-year aligned, premium)
# compare takes UUIDs; resolve tickers first (entity detail endpoint / web app).
matrix = client.compare(
entity_ids=["<apple-uuid>", "<msft-uuid>"],
hub_concept_codes=["REVENUE", "NET_INCOME"],
fiscal_year=2024,
)
for row in matrix.rows:
cell = row.cells.get("REVENUE")
if cell:
print(f"{row.name} ({row.ticker}): {cell.value:,.0f} {cell.currency}"
f" [{cell.extraction_method}]")
Audit a number to its filing
# Filing-level quality pre-screen
grade = client.get_filing_quality_grade("<filing-uuid>")
print(grade.letter_grade, grade.overall_score)
for d in grade.drivers:
print(f" {d.name}: {d.score:.2f} (w={d.weight})")
# then drill to the raw filer-declared facts (qname, unit, decimals, dimensions).
facts = client.get_filing_facts("<filing-uuid>", concept="Revenue", limit=50)
for f in facts.facts:
print(f.concept_qname, f.value_numeric, f.unit, f.dimensions)
pandas
import pandas as pd
hist = client.get_metric_history("MSFT", "REVENUE", years=10)
df = pd.DataFrame([p.model_dump() for p in hist.points])
df["source_form"] = [p.source.form_type for p in hist.points]
Reliability
- Retries
429(rate limit) +5xx(server) with exponential backoff (3 retries, base 1 s, cap 10 s); honorsRetry-Afterwhen present. - After exhausting retries on
429, raisesRateLimitError(subclass ofHubEquityError) with the lastretry_afterattached. - Other 4xx raise
HubEquityErrorimmediately (no retries), with.status_code.
from hub_equity import HubEquity, HubEquityError, RateLimitError
with HubEquity() as client:
try:
rev = client.get_metric_history("AAPL", "REVENUE")
except RateLimitError as exc:
print(f"Rate-limited, retry after {exc.retry_after}s")
except HubEquityError as exc:
print(f"{exc.status_code}: {exc}")
Rate limits
| Plan | Per minute | Per day |
|---|---|---|
| Free / anon | 60 | 5 000 |
| Pro | 300 | 100 000 |
| Enterprise | 1 000 | 500 000 |
Bucketed per API key (per JWT user, or per IP for anonymous callers). Premium
endpoints (compare, point-in-time) require a Pro/Enterprise key.
Versioning
Semantic versioning. The 1.x surface is stable: no breaking change to an
existing method or model without a major bump. Pin a version in production
(hub-equity==1.0.0). Response models use extra="allow", so additive API
changes ship in minor releases without breaking older SDK installs.
License
Apache-2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hub_equity-1.0.0.tar.gz.
File metadata
- Download URL: hub_equity-1.0.0.tar.gz
- Upload date:
- Size: 25.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f4d2bba28d9008cb53154a87485d21b10e1b3a8d065df0acc045dc365157383
|
|
| MD5 |
a28a9a88d2195ee3c1c7079aca216e7a
|
|
| BLAKE2b-256 |
79c8dabe49b990e00151d7b758a45ef893825bae1bdc0dacd718ed388dad50f3
|
Provenance
The following attestation bundles were made for hub_equity-1.0.0.tar.gz:
Publisher:
publish-sdk.yml on GLaine1/Hub-Equity_MVP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hub_equity-1.0.0.tar.gz -
Subject digest:
4f4d2bba28d9008cb53154a87485d21b10e1b3a8d065df0acc045dc365157383 - Sigstore transparency entry: 2128427590
- Sigstore integration time:
-
Permalink:
GLaine1/Hub-Equity_MVP@df44ca38d7dbf126fa946ad563fbba26aeca6c1b -
Branch / Tag:
refs/tags/sdk-v1.0.0 - Owner: https://github.com/GLaine1
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@df44ca38d7dbf126fa946ad563fbba26aeca6c1b -
Trigger Event:
push
-
Statement type:
File details
Details for the file hub_equity-1.0.0-py3-none-any.whl.
File metadata
- Download URL: hub_equity-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e256d1b272b11ee7939cd1ec78b100147272378f662aef9e8c90b592274a0d60
|
|
| MD5 |
1cf42c44093b5f5fcef23d1d5ef42db5
|
|
| BLAKE2b-256 |
7a29daa240a87aa8e4de7e246bdc77b7f1972436fccefb57359da8c6d620ffa6
|
Provenance
The following attestation bundles were made for hub_equity-1.0.0-py3-none-any.whl:
Publisher:
publish-sdk.yml on GLaine1/Hub-Equity_MVP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hub_equity-1.0.0-py3-none-any.whl -
Subject digest:
e256d1b272b11ee7939cd1ec78b100147272378f662aef9e8c90b592274a0d60 - Sigstore transparency entry: 2128427676
- Sigstore integration time:
-
Permalink:
GLaine1/Hub-Equity_MVP@df44ca38d7dbf126fa946ad563fbba26aeca6c1b -
Branch / Tag:
refs/tags/sdk-v1.0.0 - Owner: https://github.com/GLaine1
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@df44ca38d7dbf126fa946ad563fbba26aeca6c1b -
Trigger Event:
push
-
Statement type: