Fyrn
Back to blog
nordicmulti-country

One Company, Four Accounting Systems: Multi-Country Nordic Integration

How companies operating across Sweden, Norway, Denmark, and Finland end up with four different accounting systems — and how to unify them without losing your mind.

Fyrn Engineering ·

Here’s a scenario that’s more common than it should be:

A company headquartered in Stockholm opens offices in Oslo, Copenhagen, and Helsinki. Each country needs local accounting software — for compliance, for bank integrations, for tax reporting in the local format. Within 18 months, the company is running:

  • Fortnox in Sweden (SIE format, Swish payments)
  • Tripletex in Norway (SAF-T compliance, Vipps payments)
  • e-conomic in Denmark (NemHandel, MobilePay)
  • Procountor in Finland (Peppol via Maventa)

Four accounting systems. Four different APIs. Four different data models. One finance team trying to produce consolidated reports.

This isn’t a failure of planning. It’s a consequence of how Nordic software markets evolved — each country developed its own dominant solutions optimized for local tax rules, banking systems, and compliance requirements.

Why You Can’t Just Pick One

The obvious question: why not standardize on one system?

Tax reporting formats differ by country. Sweden uses SIE (a tagged text file format maintained by SIE-Gruppen since 1992). Norway mandates SAF-T (Standard Audit File for Tax, XML-based, version 1.30 as of January 2025). Denmark is adopting SAF-T. Finland has no standardized audit file format but requires specific VAT reporting structures.

Your accounting system must generate the correct format for each jurisdiction. Fortnox generates SIE natively. Tripletex generates SAF-T natively. Neither generates the other’s format correctly.

Banking integrations are country-specific. Swedish bank feeds (SEB, Nordea, Handelsbanken) integrate best with Fortnox. Norwegian bank feeds (DNB, SpareBank 1) integrate best with Tripletex. Forcing a Swedish system to connect to Norwegian banks — or vice versa — means building custom integrations with no vendor support.

Payment ecosystems don’t cross borders well. Swish (Sweden) and Vipps (Norway) are separate systems despite both being mobile payments. Klarna operates across all markets but with different checkout flows per country. MobilePay serves Denmark and Finland. Each payment system has its own reconciliation format.

E-invoicing standards vary. Norway mandates Peppol/EHF. Denmark mandates NemHandel (which is Peppol-compatible but with a Danish overlay). Sweden is voluntary for now. Finland has strong Peppol adoption through Maventa. The endpoint IDs, validation rules, and access point infrastructure differ per country.

The Data Model Problem

Even if you accept that four systems are necessary, you still need to consolidate data. This means mapping between four different representations of the same business concepts.

Take a customer record:

# Fortnox (Sweden)
customer:
  CustomerNumber: "10042"
  Name: "Acme AB"
  OrganisationNumber: "556677-8899"
  VATNumber: "SE556677889901"
  Address1: "Kungsgatan 12"
  ZipCode: "111 43"
  City: "Stockholm"
  Country: "SE"

# Tripletex (Norway)
customer:
  id: 892034
  name: "Acme AS"
  organizationNumber: "912345678"
  vatNumber: null  # Derived from org number in Norway
  address:
    addressLine1: "Karl Johans gate 22"
    postalCode: "0162"
    city: "Oslo"
    country: "NO"

# e-conomic (Denmark)
customer:
  customerNumber: 1042
  name: "Acme ApS"
  corporateIdentificationNumber: "12345678"  # CVR number
  vatNumber: "DK12345678"
  address: "Stroget 45"
  zip: "1159"
  city: "Copenhagen"
  country: "DK"

# Procountor (Finland)
customer:
  id: 78901
  name: "Acme Oy"
  businessId: "1234567-8"  # Y-tunnus
  vatIdentifier: "FI12345678"
  streetAddress: "Mannerheimintie 10"
  postCode: "00100"
  city: "Helsinki"
  country: "FI"

Same company, four subsidiaries, four completely different data structures. The fields that look equivalent aren’t always:

  • OrganisationNumber (SE) is formatted XXXXXX-XXXX. organizationNumber (NO) is XXXXXXXXX (9 digits, no dash). corporateIdentificationNumber (DK) is XXXXXXXX (8 digits, CVR). businessId (FI) is XXXXXXX-X (Y-tunnus).
  • VAT numbers follow EU formatting rules but each system stores them differently — some with the country prefix, some without, some derived from the org number.
  • Address structures range from flat strings to nested objects with different field names.

Multiply this by every business object — invoices, products, orders, payments, employees — and you’re looking at hundreds of field mappings across four systems.

The Traditional Approach: Point-to-Point Chaos

Most companies solve this with point-to-point integrations, often built by a developer in each country office:

Fortnox ←→ Data Warehouse ←→ Tripletex
              ↑       ↑
         e-conomic   Procountor

Each arrow is a custom integration. Each integration has:

  • Custom field mappings maintained in code
  • Custom error handling
  • Custom scheduling (cron jobs, usually)
  • No schema drift detection
  • No self-healing
  • No shared monitoring

When Tripletex updates their API (which they do — they moved from v1 to v2 with breaking changes), the Norwegian integration breaks and nobody finds out until the finance team complains about missing transactions.

The typical mid-market company has 2-4 dedicated engineering weeks per quarter maintaining these cross-country integrations. That’s 8-16 weeks of senior engineering time per year — spent on plumbing, not product.

The Unified API Approach

Services like Zwapgrid attempt to solve this with a unified API — one schema that normalizes data from all Nordic accounting systems:

# Zwapgrid normalized schema
invoice:
  id: "zwap_inv_001"
  source_system: "fortnox"
  customer:
    name: "Acme AB"
    tax_id: "SE556677889901"
    country: "SE"
  lines:
    - description: "Consulting services"
      quantity: 10
      unit_price: 1200.00
      vat_rate: 0.25
  total: 15000.00
  currency: "SEK"

This works well for basic read/write operations on accounting data. But unified APIs have limits:

  • Lowest common denominator. The normalized schema can only include fields that exist across all systems. Country-specific fields (SAF-T category codes, SIE account classes) get lost.
  • Write complexity. Writing data back to four systems means handling four different validation rules, four different error responses, and four different required-field sets.
  • Scope limitation. Zwapgrid covers accounting data. It doesn’t cover payroll (Hogia, SD Worx), e-invoicing (Peppol), or identity (BankID variants).

The Declarative Approach

A better model: declarative integration configs that express the business intent once and adapt per country.

flow: consolidated-invoice-sync
description: "Sync invoices from all Nordic subsidiaries to central reporting"

sources:
  - system: fortnox
    country: SE
    trigger: invoice.created
    auth: visma-connect-se

  - system: tripletex
    country: "NO"
    trigger: invoice.created
    auth: visma-connect-no

  - system: e-conomic
    country: DK
    trigger: invoice.booked
    auth: visma-connect-dk

  - system: procountor
    country: FI
    trigger: invoice.approved
    auth: procountor-oauth

transform:
  normalize:
    invoice_id: "{{ source.id }}"
    subsidiary: "{{ source.country }}"
    customer:
      name: "{{ source.customer.name }}"
      tax_id: "{{ source.customer | extract_tax_id }}"
    line_items: "{{ source.lines | normalize_line_items }}"
    total:
      amount: "{{ source.total }}"
      currency: "{{ source.currency }}"
    local_compliance:
      tax_format: "{{ country_config[source.country].tax_format }}"
      vat_reporting: "{{ country_config[source.country].vat_rules }}"

target:
  destination: data-warehouse
  action: invoices.upsert
  key: [subsidiary, invoice_id]

One flow definition. Four source systems. The normalize_line_items and extract_tax_id transforms handle the per-country data model differences. Country-specific compliance metadata is preserved, not flattened.

When Tripletex updates their API schema, self-healing detects the change and updates the Norwegian source mapping — without touching the Swedish, Danish, or Finnish configs.

Practical Steps for Multi-Country Nordic Integration

If you’re building or rearchitecting cross-country Nordic integrations:

1. Accept the four-system reality. Don’t fight it. Each country needs a locally compliant accounting system. Your integration strategy should bridge them, not replace them.

2. Define a canonical data model. Not a lowest-common-denominator model — a superset model that preserves country-specific fields in a structured way:

canonical_customer:
  name: string
  country: enum[SE, NO, DK, FI]
  tax_id:
    value: string
    format: enum[org_number_se, org_number_no, cvr_dk, y_tunnus_fi]
  local_fields: object  # Country-specific data preserved here

3. Centralize auth management. Visma Connect provides OAuth 2.0 for most Visma products. Fortnox uses its own OAuth. Procountor has its own OAuth. Manage all tokens in one credential store with automated refresh — don’t scatter credentials across cron jobs.

4. Build country-agnostic transforms with country-specific adapters. The business logic (sync invoices to reporting) is the same everywhere. The field mappings (Fortnox format → canonical, Tripletex format → canonical) differ per country. Separate these concerns.

5. Monitor per-country, alert globally. Each country integration has different failure modes (Tripletex rate limits vs. Fortnox undocumented endpoint changes vs. Procountor maintenance windows). Your monitoring should understand the per-country context but alert your central ops team.

6. Plan for compliance changes. SAF-T versions update. Peppol profiles evolve. SIE hasn’t changed much in 30 years but Skatteverket occasionally updates requirements. Build your integrations to accommodate schema evolution, not to resist it.

The Nordic software ecosystem is rich and mature — but it was built country by country, not as a unified platform. Integration is the glue that makes multi-country operations work. Build it deliberately, not as an afterthought.