SHAB API: reading Swiss gazette notices from amtsblattportal.ch
The SHAB, short for Schweizerisches Handelsamtsblatt, is the Swiss Official Gazette of Commerce: SOGC in English, FOSC in French. Every new entry, change, and deletion in a Swiss commercial register is published there: 1,030 notices on Monday 28 September 2026. The State Secretariat for Economic Affairs (SECO) serves the gazette through a public API on amtsblattportal.ch, the portal that also carries several cantonal gazettes.
This guide is for developers building a SHAB data import. If you need to interpret a gazette entry for sales, start with Reading SHAB/FOSC, which explains what each entry type means commercially.
Here we cover the publication endpoints and XML fields. We also explain four API behaviours that can waste a day when you meet them in production.
Use the public API for machine access
SHAB's robots.txt applies to automated crawling of the website. For machine access, the Amtsblattportal provides a public REST API intended for production use. Use the API endpoints below for published material. They require no login.
| Environment | Base URL |
|---|---|
| Production | https://amtsblattportal.ch/api/v1/ |
| Integration | https://int.amtsblattportal.ch/api/v1/ |
The login endpoint is for submitting publications. The open endpoints above serve published material.
List publications, then fetch each record
GET /api/v1/publications/xml returns a paginated list of publication metadata and ids. Fetch each publication body with GET /api/v1/publications/{id}/xml.
Store the id as the publication key. Check it before fetching the detail document so reruns can skip bodies you already hold.
Both endpoints support /xml, /csv, /pdf, and /docx variants.
A typical list request for a day of HR publications:
GET https://amtsblattportal.ch/api/v1/publications/xml
?publicationStates=PUBLISHED
&tenant=shab
&rubrics=HR
&publicationDate.start=2026-07-09
&publicationDate.end=2026-07-09
&pageRequest.page=0
&pageRequest.size=2000
The response is a bulk-export document. This one is trimmed from the list for 28 September 2026, requested with a page size of 2:
<bulk:bulk-export xmlns:bulk="https://shab.ch/bulk-export">
<total>1030</total>
<pageRequest>
<page>0</page>
<size>2</size>
</pageRequest>
<publication
ref="https://amtsblattportal.ch/api/v1/publications/bc692a65-d9b1-4bef-9478-3e5113f6fdea/xml"
schemaLocation="https://amtsblattportal.ch/api/v1/schemas/shab/1.26/HR02-export.xsd">
<meta>
<id>bc692a65-d9b1-4bef-9478-3e5113f6fdea</id>
<rubric>HR</rubric>
<subRubric>HR02</subRubric>
<language>fr</language>
<publicationNumber>HR02-1006767701</publicationNumber>
<publicationState>PUBLISHED</publicationState>
<publicationDate>2026-09-28</publicationDate>
<cantons>GE</cantons>
<title>
<en>Change Les Artisans Associés du Léman Sàrl, en liquidation, ...</en>
...
</title>
</meta>
</publication>
...
</bulk:bulk-export>
total counts every match for the request, so divide it by the page size and round up to know how many pages to walk. The ref attribute is the detail URL. meta.subRubric and the title in four languages are already in the list, which lets you route a record before fetching its body.
Parameters for an HR publication list
| Parameter | Value | Note |
|---|---|---|
publicationStates | PUBLISHED | Mandatory. Without it the API answers with an AccessDeniedException. |
tenant | shab | The federal commercial gazette. Cantonal tenants exist. |
rubrics | HR | Handelsregister. Use HR. The documentation listed BH when last checked. |
subRubrics | — | Ignored by the live API. See below. |
publicationDate.start / .end | ISO date | Inclusive dates at day granularity. |
cantons | ZH, GE, … | Optional. |
pageRequest.page / .size | 0-based / max 2,000 | The only documented hard limit. |
pageRequest.sortOrders | column:PUBLICATION_DATE|direction:DESC |
The subRubrics trap. In our production test, subRubrics=HR01 also returned HR02 and HR03 records. Request rubrics=HR, then classify each listed publication from meta.subRubric. Otherwise, a new-registration table can quietly include changes and deletions.
Classify each HR publication into one of these sub-rubrics:
HR01: Neueintragungen, new entries. Incorporations and branch creations.HR02: Mutationen, changes. Seat moves, address changes, name changes, capital increases, mergers.HR03: Löschungen, deletions.
Read the structured fields first
An HR detail document repeats the meta block from the list and adds a content block. Use its structured fields for company identity and attributes. They also cover common change types. Keep publicationText for acts that lack a dedicated structured field.
A new registration from 28 September 2026, trimmed:
<HR01:publication xmlns:HR01="https://shab.ch/shab/HR01-export" ...>
<meta>...</meta>
<content>
<journalNumber>6568</journalNumber>
<journalDate>2026-09-23</journalDate>
<publicationText>Immoworx AG, in Wollerau, CHE-381.329.149, Samstagernstrasse 45,
8832 Wollerau, Aktiengesellschaft (Neueintragung). ... Aktienkapital: CHF 100'000.00.
Liberierung Aktienkapital: CHF 50'000.00. ...</publicationText>
<commonsNew>
<company>
<name>Immoworx AG</name>
<uid>CHE-381.329.149</uid>
<seat>Wollerau</seat>
<legalForm>0106</legalForm>
<address>
<street>Samstagernstrasse</street>
<houseNumber>45</houseNumber>
<swissZipCode>8832</swissZipCode>
<town>Wollerau</town>
</address>
</company>
<purpose>Die Gesellschaft bezweckt ...</purpose>
<capital>
<nominal>100000.00</nominal>
<paid>50000.00</paid>
</capital>
</commonsNew>
<transaction>
<registration>true</registration>
</transaction>
</content>
</HR01:publication>
The body text writes the capital as CHF 100'000.00 and the structured field as 100000.00, so read the figure from capital.nominal and skip parsing the apostrophe. legalForm is a code from the Federal Statistical Office's legal-form list (eCH-0097): 0106 for an AG (SA), 0107 for a GmbH (Sàrl).
| Need | Read from | Detail |
|---|---|---|
| Identity and deduplication | meta.id | Publication UUID |
| Publication type | meta.rubric, meta.subRubric | Already present in the list response |
| Company after the publication | content.commonsNew | Name, seat, UID, legal form, address, capital |
| Company before the publication | content.commonsActual | Same fields, in HR02 and HR03 documents |
| Change type | content.transaction | registration, update, or delete |
| Register journal reference | content.journalDate, content.journalNumber | Tagebuch entry and effective date |
| Previous notice | content.lastFosc | Date, issue number, and sequence number of the company's previous gazette notice |
HR02 records expose change flags under transaction.update.changements, including seatChanged, addressChanged, nameChanged, purposeChanged, and capitalChanged, which splits into nominal and paid. Liquidation and bankruptcy steps have their own statusChanged block. For a name change, compare the name in commonsActual with the one in commonsNew. To identify a capital increase, compare commonsActual.capital.nominal with commonsNew.capital.nominal when capitalChanged.nominal is true. Keyword detection over the publication text is still useful for mergers and branch creations, which lack a dedicated structured flag.
The schemas are published at https://amtsblattportal.ch/api/v1/schemas/bulk-export.xsd and per sub-rubric at https://amtsblattportal.ch/api/v1/schemas/shab/1.26/HR0x-export.xsd.
Validate capital figures
Swiss display text uses an apostrophe as the thousands separator, and the gazette occasionally publishes one where a decimal point belongs. We have seen a capital figure overstated by a factor of a hundred that way. The record rose to the top of a monthly capital-increase report before the anomaly was caught.
Flag an SA below CHF 100,000 nominal capital and a GmbH below CHF 20,000 for review. Also flag a single mutation that changes nominal capital by 100 times or more. These checks identify likely parsing or source-data errors. Send the record to review and preserve the original value.
Reconcile cancellations in every daily run
A publication can be PUBLISHED or CANCELLED. Reconcile both states on every run because a cancellation may affect a publication already stored or acted on.
Run the two states as separate passes and dedupe the overlapping ids with CANCELLED winning. Reconcile the body against the state you discovered it under. Some bodies omit the field.
The daily reconciliation algorithm:
- List both
PUBLISHEDandCANCELLEDrecords for the previous seven calendar days through today. Keep one row per id, withCANCELLEDtaking precedence if the id appears in both lists. - Upsert the state for every listed id, including ids already stored. This is how a previous publication becomes cancelled in your database.
- Fetch detail documents for ids whose body is missing or whose state change requires another copy. Cap concurrency and retry transient failures with exponential backoff.
- Parse structured fields first. Use
publicationTextfor the remaining acts.
In 305,902 publications measured over the past twelve months, the median interval between a change taking effect and its publication was five days. Of those publications, 38% appeared within three days. We re-list the previous seven calendar days on every daily run to absorb late and corrected records.
For scale: on 9 July 2026 there were about 1,310 HR publications out of roughly 1,813 SHAB publications that day.
An open-source parser for these publications
The parser behind our own import is published under the MIT licence as python-shab-parser. It reads an Amtsblattportal XML document into typed dataclasses, then classifies each publication into events: incorporation, seat move, capital increase, deletion. Namespace differences between the sub-rubrics are absorbed, so an HR01, HR02 or HR03 document parses the same way.
Its optional HTTP client covers the discovery and fetch loop described above, rate-limited to one request per second, with exponential backoff on transient failures. The documentation sets out the event types and the full API reference.
Usage terms and legal status
The operator's terms disclaim completeness and accuracy. The signed PDF is the legally authoritative version of each publication. Review the current API terms before commercial reuse. This guide describes our technical implementation and is not legal advice.
A gazette notice tells you which legal change was published. Deciding whether the company is worth contacting usually requires context from its website and current hiring.
Where Swiss company data actually lives explains those sources, and what each of them is good for compares them on the questions a daily import has to answer. For the register record behind a notice, with its UID and EHRA-ID, see the Zefix API guide. Public tenders and awards come from simap.ch, and the vendor profile behind an award usually carries the winner's UID: see the SIMAP API guide.
Frequently asked questions
- Does the SHAB API need an API key?
- No. Published notices on amtsblattportal.ch/api/v1 can be read without a key or a login. The login endpoints are for submitting publications.
- Why does the SHAB API answer "Access is denied"?
- Usually because the list request is missing publicationStates, which the API reports as an AccessDeniedException. Add publicationStates=PUBLISHED, or CANCELLED for the cancellation pass, and the same request returns records.
- Are SHAB, SOGC and FOSC the same gazette?
- Yes. SHAB is the German abbreviation of Schweizerisches Handelsamtsblatt. The Swiss Official Gazette of Commerce is SOGC in English, FOSC in French, and FUSC in Italian. The API uses the tenant code shab for every language.
- How many publications does one request return?
- Up to 2,000, set with pageRequest.size. Recent working days carried 1,030 commercial register notices (28 September 2026) and about 1,310 (9 July 2026), so a day usually fits on one page. The total element in the response tells you whether to request the next page.