Skip to main content

zefix-parser

Documentation

Typed Python client for Zefix, the Swiss Central Business Name Index (Zentraler Firmenindex).

Covers both ways into the register: the open LINDAS SPARQL dataset, which carries every company in Switzerland and needs no credentials, and the Zefix PublicREST API, which adds share capital, legal status, auditors and corporate relations. Responses parse into plain dataclasses.

Built and maintained by Prospex, a Swiss B2B sales intelligence platform.

Install

pip install zefix-parser

To use the HTTP clients (for fetching from the live endpoints):

pip install zefix-parser[http]

Quick start

Read the register from LINDAS

No credentials needed.

from zefix_parser.client import LindasClient

with LindasClient() as client:
    print(client.count())  # 812,000 or so

    for entity in client.iter_entities():
        print(entity.legal_name, entity.uid, entity.canton, entity.legal_form_code)

Or look up companies you already have UIDs for, in one request:

from zefix_parser.client import LindasClient

with LindasClient() as client:
    entities = client.fetch_by_uids(["CHE-105.215.703", "CHE-411.462.297"])

for entity in entities:
    print(entity.legal_name)   # "Alpenblick Handel AG"
    print(entity.purpose)      # "Handel mit Waren aller Art"
    print(entity.municipality_name, entity.canton)

Fetch details from the PublicREST API

The REST API is gated behind HTTP Basic auth. Credentials are issued on request by zefix@bj.admin.ch.

from zefix_parser.client import ZefixRestClient

with ZefixRestClient(username="...", password="...") as client:
    company = client.get_by_uid("CHE-105.215.703")

print(company.name)             # "Alpenblick Handel AG"
print(company.capital_nominal)  # Decimal("250000.00")
print(company.status)           # "ACTIVE"

for auditor in company.audit_companies:
    print(auditor.name, auditor.legal_seat)

Both clients rate-limit themselves to one request every half second and retry transient failures with exponential backoff.

Parse responses you already have

Every parser is importable without the http extra, so you can point them at recorded responses or use your own HTTP library:

from zefix_parser import parse_company, parse_entity_page

company = parse_company(rest_json)          # a dict from the REST API
entities = parse_entity_page(sparql_bytes)  # a SPARQL JSON results document

The two access paths

LINDAS PublicREST
Endpoint https://ld.admin.ch/query https://www.zefix.admin.ch/ZefixPublicREST/api/v1
Credentials none HTTP Basic
Shape the whole register, keyset-paginated one company per request
Carries name, legal form, address, canton, purpose the above plus capital, status, auditors, branches, mergers, former names
Class RegistryEntity Company

LINDAS has no modification-date predicate, so a server-side delta fetch is impossible: you either walk the whole register or drive updates from another change feed, such as SHAB publications.

Data model

parse_entity_page() returns RegistryEntity objects:

@dataclass(frozen=True)
class RegistryEntity:
    zefix_uri: str
    uid: str                     # CHE123456789, unpunctuated
    chid: str
    ehra_id: str
    legal_name: str
    alternate_names: list[str]   # the other language variants
    legal_form_code: str         # eCH-0097, e.g. "0106"
    legal_form_name: str
    municipality_id: str         # federal municipality number
    municipality_name: str
    canton: str
    street_address: str
    postal_code: str
    locality: str
    purpose: str
    purpose_language: str
    fingerprint: str             # SHA-256 over the identity fields

parse_company() returns Company objects:

@dataclass(frozen=True)
class Company:
    name: str
    ehraid: int
    uid: str
    chid: str
    canton: str
    status: str                  # "ACTIVE", "IN_LIQUIDATION", "DELETED"
    capital_nominal: Decimal | None
    capital_currency: str
    deletion_date: date | None
    cantonal_excerpt_web: str
    head_offices: list[RelatedEntity]
    further_head_offices: list[RelatedEntity]
    branch_offices: list[RelatedEntity]
    has_taken_over: list[RelatedEntity]
    was_taken_over_by: list[RelatedEntity]
    audit_companies: list[RelatedEntity]
    old_names: list[OldName]

Identifiers

The same UID appears in three forms depending on where you read it, so the library converts between them:

from zefix_parser import clean_uid, format_uid, is_valid_uid, normalize_uid

normalize_uid("CHE-105.215.703")            # "CHE105215703"  (LINDAS form)
format_uid("CHE105215703")                  # "CHE-105.215.703"  (REST form)
clean_uid("VAT: CHE-109.807.630 MWST")      # "CHE109807630"
is_valid_uid("CHE123456789")                # False - the check digit fails

is_valid_uid() runs the ISO 7064 mod 11-10 check digit. It is worth calling before you spend a request: a mistyped UID can never match the register, and the register's own placeholder CHE123456789 fails it.

Legal forms

Both registers identify a legal form by its four-digit eCH-0097 code, and the name differs by language:

from zefix_parser import LegalForm, legal_form_abbreviation, legal_form_name

LegalForm.CORPORATION                    # "0106"
legal_form_name("0106", "de")            # "Aktiengesellschaft"
legal_form_name("0106", "fr")            # "Société anonyme"
legal_form_name("0106", "it")            # "Società anonima"
legal_form_abbreviation("0107", "fr")    # "Sàrl"

The full table is in the legal forms reference.

Former names

The register re-typesets a company's name whenever anything else about it changes, so company.old_names fills up with entries that differ from the current name only in casing or spacing: "QualiCasa AG" against "Qualicasa AG". Apply them and you retire the company's live name. meaningful_old_names() drops them:

from zefix_parser import meaningful_old_names

for old in meaningful_old_names(company):
    print(old.sequence_nr, old.name)   # only the genuine renames, oldest first

API reference

zefix_parser.parse_entity_page(content: bytes) -> list[RegistryEntity]

Parse a SPARQL JSON results document into companies. One company spans several rows, one per language-tagged literal; rows are grouped by entity URI and folded down to a single deterministic value per field.

zefix_parser.parse_company(data: dict | list) -> Company

Parse one /company/... response. The API is inconsistent about whether a single company comes back as an object or a one-element list; both work.

zefix_parser.build_combined_page_query(*, cursor_after=None, limit=500) -> str

Build the SPARQL query for one keyset page of full records. Use this to run the crawl yourself, outside LindasClient.

zefix_parser.client.LindasClient

SPARQL client. count(), iter_entities(), iter_pages() (which yields RawPage objects carrying the cursor, so a crawl can be resumed), fetch_by_uids(), query().

zefix_parser.client.ZefixRestClient

PublicREST client. get_by_uid(), get_by_ehraid(), get_by_chid(), search(), sogc_by_date(), sogc().

Background

Zefix (the Zentraler Firmenindex, index central des raisons de commerce, indice centrale delle ditte, officially the Swiss Central Business Name Index) is the federal index over the 26 cantonal commercial registers: Handelsregister, registre du commerce, registro di commercio. Every company registered in Switzerland appears in it, identified by a UID (CHE-123.456.789), a CHID and an EHRAID.

The Federal Office of Justice publishes the index twice. LINDAS carries every company as linked data, open to anyone, holding each company's current state. The PublicREST API holds more per company, behind credentials, and answers one lookup at a time. Neither publishes a change feed; for that you need the gazette, which is what shab-parser reads.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zefix_parser-0.1.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zefix_parser-0.1.0-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file zefix_parser-0.1.0.tar.gz.

File metadata

  • Download URL: zefix_parser-0.1.0.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for zefix_parser-0.1.0.tar.gz
Algorithm Hash digest
SHA256 88aeb3e3e4ad6f0125733f9291075241272e385773f94101b7fafbf0b00e937e
MD5 0f62d446ea80b0068dd29511bec8caf8
BLAKE2b-256 f0c9bae67b781a2d19b30648f3c0b1f8f1e167f889c8bc3fe28d8f5058a99635

See more details on using hashes here.

File details

Details for the file zefix_parser-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: zefix_parser-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for zefix_parser-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 68cde3f634edcb119a787b7dd567652199b52ba54254580de235a79404c31c1f
MD5 ce7b438858e4640e7341a9ddd73705e6
BLAKE2b-256 02b5a1f1f028cfa09fc018c77f27514047df939c45b7cf7a43280f1c4d4b35a6

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page