Python SDK
The Arche Python SDK wraps the same public routes documented in the API reference with typed models, pagination helpers, and structured errors. It is the recommended integration path for production workloads.
Install
pip install arche-sdk
Create a client
The client is a context manager. It holds a connection pool, so create one and reuse it rather than constructing a client per request.
import os
from arche_sdk import ArcheClient
with ArcheClient(api_key=os.environ["ARCHE_API_KEY"]) as client:
company = client.companies.get("0000320193")
print(company.entity_name)
- Name
api_key- Type
- str | None
- Description
Sent as the
X-Api-Keyheader. Create one in the developer portal.
- Name
base_url- Type
- str
- Description
Defaults to
https://api.arche.fi.
- Name
timeout_seconds- Type
- float
- Description
Per-request timeout. Defaults to
30.0.
- Name
http_client- Type
- httpx.Client | None
- Description
Supply your own transport when you need custom retries, proxies, or connection limits.
Pass exactly one credential. Supplying both api_key and
bearer_token raises an error rather than silently picking one.
Resources
The client exposes four resource groups:
- Name
client.companies- Type
- resource
- Description
Resolve tickers to canonical issuers, read company profiles, and check reporting completeness.
- Name
client.filings- Type
- resource
- Description
List filings for a company, read one filing, and list the statements it contains.
- Name
client.statements- Type
- resource
- Description
Statement versions, restatement timelines and deltas, reconciliation, data-quality overlays, derived metrics, and point-in-time financials.
- Name
client.narratives- Type
- resource
- Description
Narrative disclosures attached to filings.
The quickstart flow in Python
This mirrors the Quickstart step for step.
import os
from arche_sdk import ArcheClient
with ArcheClient(api_key=os.environ["ARCHE_API_KEY"]) as client:
# Step 2 - resolve a ticker to a canonical CIK
resolved = client.companies.resolve("MSFT")
# Step 3 - list statement versions for that issuer
statements = client.statements.list(
resolved.cik,
statement_type="INCOME_STATEMENT",
page=1,
page_size=10,
)
print(statements.total, "statement versions")
# Step 4 - ask what was knowable on a historical date
point_in_time = client.statements.get_as_of_financials(
"2024-03-31",
"0000320193",
)
print(point_in_time.snapshot_hash)
Derived metrics come from the same resource:
series = client.statements.get_derived_metrics_time_series(
ciks=["0000320193"],
statement_type="INCOME_STATEMENT",
metrics=["GROSS_MARGIN"],
frequency="annual",
)
print(len(series.points))
Pagination
Collection methods return a typed Page with page, page_size, total,
items, and a has_next property.
page = client.statements.list("0000320193", statement_type="INCOME_STATEMENT")
while True:
for version in page.items:
print(version.fiscal_year, version.fiscal_period)
if not page.has_next:
break
page = client.statements.list(
"0000320193",
statement_type="INCOME_STATEMENT",
page=page.page + 1,
)
For straightforward full scans, iter_all handles the loop and yields items
across page boundaries:
for version in client.statements.iter_all("0000320193", statement_type="INCOME_STATEMENT"):
print(version.fiscal_year, version.fiscal_period)
See Pagination for the underlying wire contract and Rate limits for guidance on how aggressively to iterate.
Request IDs
The SDK sends an X-Request-ID header on every request, generating a UUID when
you do not supply one. Pass your own to correlate an API call with a job or task
in your own system:
from arche_sdk import RequestOptions
company = client.companies.get(
"0000320193",
options=RequestOptions(request_id="nightly-refresh-2026-03-01"),
)
RequestOptions also accepts headers and timeout_seconds for per-request
overrides. See Request IDs for how these values
are used when escalating a failure.
Error handling
Failures raise typed exceptions. APIError is the base for any error the API
reported, and the subclasses map to HTTP status classes: AuthenticationError,
PermissionDeniedError, NotFoundError, ValidationError, ConflictError,
RateLimitError, and ServerError. Transport failures raise ConnectionError
or TimeoutError instead.
from arche_sdk import ArcheClient, APIError, RateLimitError
try:
with ArcheClient(api_key=os.environ["ARCHE_API_KEY"]) as client:
client.companies.get("0000000000")
except RateLimitError:
... # back off, then retry
except APIError as exc:
print(exc.status_code, exc.code, exc.trace_id, exc.request_id)
Every APIError carries both identifiers: request_id is the value the SDK
sent, and trace_id is the one Arche returned in the
error envelope. Log both.