orakel
Docs navigation

Canonical

Bolagsverket + SCB (Sweden)

Swedish company register — Bolagsverket base + SCB NACE overlay + HVD iXBRL financials.

Updated 2026-04-21

Source: Bolagsverket (Swedish Companies Registration Office) and SCB (Statistiska centralbyrån / Statistics Sweden) Data: Swedish companies (Bolagsverket HVD Valuable Datasets) with a NACE code overlay from SCB License: Bolagsverket HVD data is released as public-sector information under EU High-Value Dataset terms — verify the exact wording against the bulk file's README or Bolagsverket's data portal. SCB's bulk file ships under its own open-data terms. Attribution required: Yes — credit "Bolagsverket" for companies and "Statistiska centralbyrån (SCB)" for NACE Link: https://bolagsverket.se (company register), https://www.scb.se (statistics) Update cadence: se-bulk runs daily (0 5 * * *, 05:00 UTC). Each run re-downloads both bulk files and upserts the full SE universe.

What it is

Bolagsverket is Sweden's national company register. Orakel ingests the full Bolagsverket bulk file (HVD Valuable Datasets — free, weekly-refreshed ZIP) and overlays NACE industry codes from SCB's bulk file in the same daily pass.

This is Phase 3a: company base plus industry code. Financials are not yet integrated — see Limitations and "Phase 3b" below.

Swedish orgNumbers are 10 digits (e.g. 5560000000), compared with 9 for Norway and the NNNNNNN-N format for Finland. All three fit under the composite (country, orgNumber) key on the Company model.

Fields provided

Rows are stored under country = "SE" in the Company model. Bolagsverket populates the base record; SCB overlays NACE codes and the Swedish juridisk-form description.

Field Type Notes
orgNumber string (10 digits) From Bolagsverket. Part of the composite key (country, orgNumber).
country string Always "SE".
name string From Bolagsverket organisationsnamn (first $-separated segment).
orgFormCode string Short code from Bolagsverket organisationsform, with the -ORGFO suffix stripped (e.g. AB, HB, KB).
orgFormDescription string From SCB jurForm (Swedish juridisk-form text). Null when the orgNumber has no SCB match.
naceCode1 / naceCode2 / naceCode3 string From SCB ng1 / ng2 / ng3. NACE codes come from SCB, not Bolagsverket.
naceDescription1 string From Bolagsverket verksamhetsbeskrivning (free-text activity description).
businessAddressStreet / businessAddressZip / businessAddressCity string Parsed from Bolagsverket postadress ($-separated: street, street2, city, zip, country).
foundingDate / registrationDate date Both set to Bolagsverket registreringsdatum.
isBeingDissolved bool True when Bolagsverket avregistreringsdatum is populated.

Fields not populated for SE rows (null / default): naceDescription2, naceDescription3, employeeCount, hasRegisteredEmployees, businessAddressMuni, businessAddressMuniNo, postalAddress*, website, phone, parentOrgNumber, registeredInVat, registeredInBiz, isBankrupt, isInGroup, sectorCode, sectorDescription. These are not in the HVD API or the SCB bulk file.

Endpoints that surface this data

  • GET /api/companies/:orgNumber?country=SE — full company record for a Swedish 10-digit orgNumber.
  • GET /api/companies?country=SE — search / list Swedish companies.

Limitations

The KNOWN_GAPS.SE entries from lib/countries.ts, verbatim:

  • roles — requires separate Bolagsverket «Företagsinformation» credential (apply when customer asks)
  • financials coverage — HVD contains only digitally filed iXBRL from FY 2020+; digital filing was voluntary through FY 2025 so large/listed ABs (Volvo, H&M, Ericsson) historically filed PDF and are absent. Mandatory FY 2026 → first large-AB filings arrive spring 2027.
  • financials pre-2020 — paper-only, no digital history

Gotchas

  • Null bytes in upstream data. The Bolagsverket bulk file occasionally contains 0x00 bytes in text fields. Postgres rejects these with invalid byte sequence for encoding "UTF8": 0x00. Orakel's parser strips them before upsert, with a stream-idle watchdog to catch upstream stalls.
  • orgNumber length varies by country. SE orgNumbers are 10 digits; NO is 9; FI is NNNNNNN-N. Never assume a length — always use the composite (country, orgNumber) key and pass country explicitly.
  • SCB file is Latin-1. The SCB bulk file is encoded as ISO-8859-1; Orakel transcodes to UTF-8 on ingest via iconv.decodeStream("latin1") in lib/bolagsverket/client.ts. SCB tab-delimited parsing lives in lib/bolagsverket/scb.ts.
  • NACE codes come from SCB, not Bolagsverket. The two bulk files are independently refreshed. The SCB pass runs second and overlays NACE codes via a single UPDATE ... FROM (VALUES ...) per batch. Bolagsverket re-runs deliberately do not touch SCB-owned columns — flushCompanies in lib/sync/se/bulk-sync.ts only updates BV-owned columns on conflict, so SCB enrichment survives a Bolagsverket-only refresh.
  • Duplicate orgNumbers in the Bolagsverket file. Bolagsverket emits multiple rows per orgNumber for namnskyddslopnummer (name-protection) variants. Each batch is deduped before upsert (last occurrence wins) to avoid Postgres error code 21000.
  • 12-digit SCB orgNumbers. SCB sometimes prefixes a legal-person orgNumber with county indicator 16; normalizeScbOrgNumber strips the prefix to match Bolagsverket's 10-digit form. 12-digit personal identity numbers (YYMMDDxxxx, natural-person enskild firma) are skipped in Phase 3a.

Annual financial statements (Phase 3b)

Kundanmälan credentials landed 2026-04-21 and Phase 3b ships the iXBRL financials pipeline.

Source: Bolagsverket Värdefulla Datamängder (HVD) API, scope vardefulla-datamangder:read. Base URL https://gw.api.bolagsverket.se/vardefulla-datamangder/v1.

Pipeline (lib/bolagsverket/):

  1. OAuth2 client-credentials token fetch against https://portal.api.bolagsverket.se/oauth2/token (in-memory token cache with 60s skew) — oauth.ts
  2. POST /dokumentlista { identitetsbeteckning } → list of filings (dokumentId, rapporteringsperiodTom, ...) — hvd-client.ts
  3. GET /dokument/{dokumentId} → raw application/zip bytes (1-2 XHTML files: iXBRL annual report, optional audit report)
  4. Unzip + pick the XHTML whose <html> tag carries xmlns:se-gen-base (that's the iXBRL) — zip.ts
  5. Parse inline-XBRL (ix:nonFraction facts + ix:resources contexts + xbrli:unit measures) — ixbrl.ts
  6. Map se-gen-base:* concepts → Financial columns (revenue, operatingCosts, operatingResult, netFinancials, preTaxProfit, netResult, totalAssets, totalEquity, totalDebt). totalDebt is computed (no single concept). — taxonomy-k2-k3.ts
  7. Upsert into Financial with country="SE", regnskapstype="SELSKAP", currency SEKlib/sync/se/financial-sync.ts

Coverage: AB companies only, 2020+ digital filings. The HVD dataset is scoped by Bolagsverket to only annual reports submitted in iXBRL through the digital e-tjänst; PDF/paper filings held by Bolagsverket are out of scope. Digital filing was voluntary for fiscal years 2020–2025 — the e-tjänst technically accepts both K2 and K3 (since 2019), but the auditor-channel filings that large listed groups use have overwhelmingly stayed on PDF. Consequence: large listed companies (Volvo, H&M, IKEA, Atlas Copco, ABB, Klarna, SAS, Ericsson, Vattenfall) all return 0 filings pre-FY 2026. Digital filing becomes mandatory for all AB from fiscal years starting after 31 Dec 2025 — first statutory iXBRL filings from large ABs are expected to land spring/summer 2027. Until then expected coverage is the small-and-mid-sized segment of the ~587K SE AB.

Taxonomies: K2 (smaller companies, observed se-k2-type namespace) and K3 (larger) under the Swedish se-gen-base family. Current concept map was built against three real K2 filings; K3 aliases will be added as they're encountered.

Cadence: SE financials refresh daily after the company-level refresh, batch size 500 companies/run, oldest-updated-first.

Scope caveat — roles still NOT available: The V-D credential only grants vardefulla-datamangder:read. The companion Företagsinformation v4 API (which would expose funktionarer, firmateckning, aktieinformation, organisationsengagemang as structured JSON) requires a separate foretagsinformation:read credential. Roles ship when a paying customer asks and the second credential is applied for.