Python SDK
SDKs

Python SDK

A modern Python client for the Handelsregister.ai API. Access German commercial-register company data, financials, management, ownership, person profiles, Signals, and official documents.

AGPL-3.0 licensed

Installation and authentication

pip install handelsregister

export HANDELSREGISTER_API_KEY=your_api_key_here
# Or: export HANDELSREGISTER_BEARER_TOKEN=your_token_here

Use an API key for server-to-server integrations, or a Bearer token for scoped, expiring access. If both are provided, the Bearer token wins. Pass proxy headers through extra_headers or JSON via HANDELSREGISTER_EXTRA_HEADERS; managed authentication and User-Agent headers cannot be overridden.

import os
from handelsregister import Handelsregister

client = Handelsregister(api_key=os.environ["HANDELSREGISTER_API_KEY"])
# client = Handelsregister(bearer_token=os.environ["HANDELSREGISTER_BEARER_TOKEN"])

Company and person lookup

Use fetch_organization() for direct results with configurable feature flags. Set ai_search="on-default" for AI search. realtime_mode="handelsregister-default" performs a live lookup (+10 credits); it cannot be combined with related_persons or publications.

result = client.fetch_organization(
    q="KONUX GmbH München",
    features=["related_persons", "financial_kpi", "shareholders"],
    ai_search="on-default",
)
print(result["name"], result["registration"]["register_number"])

The Company interface provides typed access to company, people, ownership, representation, M&A, news, and financial data. Its properties include registration, address, contact data, financial statements, related-person entries, shareholders, UBOs, shareholdings, and representation rules.

from handelsregister import Company

company = Company(
    "OroraTech GmbH München",
    features=["related_persons", "financial_kpi", "shareholders", "ubos",
              "shareholdings", "mergers_and_acquisitions", "news"],
)
print(company.name, company.is_active, company.formatted_address)
for person in company.current_related_persons:
    print(person["name"], person["role"]["en"]["long"])
for entry in company.shareholders.entries:
    print(entry.display_name, entry.percentage)
for ubo in company.ubos.resolved:
    print(ubo.name, ubo.percentage)
for holding in company.shareholdings.current:
    print(holding.organization_name, holding.percentage)

/v1/fetch-person combines Handelsregister records with public web data. AI search is always on, and the 15-credit base cost includes enrichment. Supply organization_q to disambiguate common names; shareholdings costs 5 credits only when data is returned.

from handelsregister import Person

person = Person(
    person_q="Max Mustermann",
    organization_q="Beispielwerk Analytics GmbH",
    features=["shareholdings"],
)
print(person.canonical_name, person.home_city)
for role in person.handelsregister_roles:
    print(role["name"], role["label"], role.get("start_date"))

Search and Signals

Search by query, filters, or both. Filters cover registration dates, legal forms, WZ/NACE industries, active status, location and radius, register data, company size, employees, balance-sheet values, revenue, net income, and EBIT. Use RangeFilter or a dictionary with gte/lte.

from handelsregister import RangeFilter, SearchFilters

page = client.search_organizations(
    limit=10,
    filters=SearchFilters(
        city="München", legal_form_code=["GmbH", "AG"], active=True,
        pl_revenue=RangeFilter(gte=1_000_000, lte=5_000_000),
    ),
    ai_mode="on-default",
)
organizations = list(client.iter_search_organizations(
    q="tech", page_size=30, max_results=100,
))

The API returns at most 30 organizations per request; a larger limit raises ValueError. Each iterator page is separately billable and is fetched only when reached.

Signals are cursor-paginated company changes. The catalog is free; successful list and detail requests cost 20 credits, and each page contains 20 signals.

from handelsregister import SignalTopic

page = client.list_signals(
    topics=[SignalTopic.CAPITAL_CHANGES, SignalTopic.TRANSFORMATIONS],
    organization_ids=["0123456789abcdef0123456789abcdef"],
    from_date="2026-07-01", to_date="2026-07-30",
)
catalog = client.get_signal_catalog()
detail = client.get_signal(page["signals"][0]["event"]["id"])

for signal in client.iter_signals(
    topics=[SignalTopic.NEW_REGISTRATIONS], max_results=50,
):
    print(signal["organization"]["current_profile"]["name"])

list_signals() accepts opaque cursor, topics, organization IDs (OR semantics), and inclusive dates. Public topics are NEW_REGISTRATIONS, MASTER_DATA_CHANGES, CLOSURES, ROLE_HOLDER_CHANGES, CAPITAL_CHANGES, INSOLVENCIES (Pro), and TRANSFORMATIONS (Max). Unavailable topics raise SubscriptionRequiredError and cost zero credits. List items include event, organization, parties, register entry, source, topic-specific details, pagination, filters, warnings, and metadata.

Monitoring and webhooks

Monitoring pushes normalized company changes to signed HTTPS endpoints. Reads are free. Mutations need an API key or a Bearer token with account:read and monitoring:manage; endpoint administration also needs account:keys. Use the SDK to list endpoints, deliveries, and events, retry retained failed deliveries, rotate secrets, and disable or archive endpoints.

client = Handelsregister(bearer_token="YOUR_ADMIN_TOKEN")
created = client.create_webhook_endpoint(
    name="Production receiver",
    url="https://hooks.example.com/handelsregister",
)
endpoint_id = created["endpoint"]["id"]
signing_secret = created["signing_secret"]  # shown exactly once
client.verify_webhook_endpoint(endpoint_id)
client.test_webhook_endpoint(endpoint_id)

monitor = client.create_monitor(
    entity_id="cc78cf0b230aeae35c6df7ba31989bb9",
    poll_interval_days=7, endpoint_ids=[endpoint_id], label="BMW AG",
)["monitor"]
client.pause_monitor(monitor["id"])
client.resume_monitor(monitor["id"])
client.archive_monitor(monitor["id"])

The asynchronous baseline is free and suppresses historical observations. Activation has a 10-credit rolling 30-day floor for five complete successful checks; further complete checks cost 2 credits. Failed, partial, superseded, or unfunded checks cost nothing.

from handelsregister.webhooks import construct_event, verification_response_headers

event = construct_event(raw_body_bytes, request_headers, signing_secret)
if event["type"] == "endpoint.verification":
    return Response(status=204, headers=verification_response_headers(event))
if event["type"] == "organization.signal.detected":
    signal = event["data"]["signal"]

Delivery is at least once and unordered. Verify the exact raw body with HMAC-SHA256 and deduplicate by message ID; the previous secret remains valid for seven days after rotation. Any 2xx succeeds; failures are retried for roughly three days. Every mutation uses an Idempotency-Key; the SDK reuses it for internal retries, and idempotency_key= supports restart-safe retries.

Account and usage

Account reads cost zero credits. API-key creation and revocation require a Bearer token with account:keys; other reads accept an API key or account:read Bearer token. Usage supports a maximum 366-day range; date-only to_date includes the full day, and transactions use opaque cursor pagination.

client = Handelsregister()
profile = client.get_account()
credits = client.get_account_credits()
subscription = client.get_account_subscription()
keys = client.list_api_keys()
usage = client.get_account_usage(
    from_date="2026-07-01", to_date="2026-07-30", group_by="day",
)
for transaction in client.iter_account_usage_transactions(per_page=100):
    print(transaction["endpoint"], transaction["credits"])

Documents, tokens, enrichment, and CLI

Supported document types are shareholders_list, articles_of_association, AD, CD, and SI. Bearer-token management supports creation, listing, individual revocation, and deliberate revocation of all tokens. ["*"] is not a wildcard: it becomes api:data and account:read.

entity_id = client.fetch_organization(q="KONUX GmbH München")["entity_id"]
client.fetch_document(company_id=entity_id, document_type="shareholders_list",
                      output_file="konux_shareholders.pdf")
pdf_bytes = client.fetch_document(company_id=entity_id, document_type="CD")
xml_bytes = client.fetch_document(company_id=entity_id, document_type="SI",
                                  output_file="konux_structured.xml")

client.enrich(
    file_path="companies.csv", input_type="csv",
    query_properties={"name": "company_name", "location": "city"},
    snapshot_dir="snapshots",
    params={"features": ["related_persons", "financial_kpi", "ubos"]},
    output_file="companies_enriched.csv", output_type="csv",
)

Enrichment supports CSV, JSON, XLSX, and DataFrames. Snapshots resume long jobs and outputs retain input fields plus _handelsregister_result and _in_file. The CLI also supports raw JSON, filters-only search, document downloads, monitor lifecycle operations, webhook endpoints, deliveries, and events.

handelsregister fetch "KONUX GmbH München"
handelsregister person --person "Max Mustermann" --organization "Beispielwerk Analytics GmbH"
handelsregister search "tech" --postal-code 80992 --limit 20
handelsregister document "KONUX GmbH München" --type SI --output konux_structured.xml
handelsregister monitors pricing --interval 7
handelsregister webhooks events

Feature flags, errors, and security

Available company features: related_persons, financial_kpi, balance_sheet_accounts, profit_and_loss_account, annual_financial_statements, annual_financial_statements__html, publications, insolvency_publications, news, website_content, shareholders, ubos, shareholdings, and mergers_and_acquisitions. Ownership and M&A features are beta.

All API exceptions inherit from HandelsregisterError. Mapped errors include validation, authentication, insufficient-credit, forbidden/subscription, not-found, conflict/idempotency, rate-limit, timeout, server/service-unavailable, and webhook-signature errors. Exceptions retain status_code, JSON payload, and billing meta. Only network failures, HTTP 408/429, and server errors are retried. Keep credentials out of source control and revoke an exposed key or token.

For the complete, current SDK reference and runnable examples, see the Handelsregister Python SDK repository.