FinchContext
Run with

Build the Loonaangifte Payroll Declaration

Skill: Convert payroll data into the Dutch Loonaangifte XML

Region: Netherlands (Nederland) Category: Payroll — Loonaangifte (loonheffingen) for the Belastingdienst Does: Takes a period payroll run and produces the Loonaangifte XML — the periodic wage-tax-and-contributions declaration filed with the Belastingdienst, combining a collective return (Collectief) of period totals with a nominative return (Nominatief) of one record per employee keyed by BSN. Standard: Belastingdienst Loonaangifte (Gegevensspecificaties Aangifte Loonheffingen) — XML message delivered over Digipoort / BAPI; the specification is reissued each tax year (2026 version).

The loonaangifte is a structured XML message lodged through Digipoort (or a certified payroll package) with PKIoverheid authentication — not a portal form. The Belastingdienst reconciles the Collectief totals against the sum of every Nominatief employee record, so the two must tie exactly. Code lists (sectoraansluiting, codes for Awf/Aof/Whk, incidentele inkomstenvermindering, etc.) and premium percentages change every year; validate against the current year's Gegevensspecificaties before sending. Amounts are in eurocenten (whole cents, no decimal point).


When this applies


Conversion procedure

  1. Read the source. Accept the payroll run as CSV/JSON (one row per employee: BSN, name, gross wage, loon LB/PH, loon SV, ingehouden loonheffing, premium bases) or a payroll-system export. Parse rows directly; OCR/pdftotext a scanned loonstaat first.
  2. Identify the employer and tijdvak. Capture the loonheffingennummer (BSN/RSIN + L + sub-number), the aangiftetijdvak (start/end dates), and the assigned sector/premium settings.
  3. Build one Nominatief record per employee. Key each on the BSN (or, if no BSN, the personeelsnummer plus identifying data). Fill the inkomstenverhouding (income relationship) with loon SV, loon LB/PH, the ingehouden loonheffing, and the premium bases for Awf, Aof, Whk and Zvw.
  4. Classify the Awf premium. Tag each income relationship as Awf hoog or Awf laag (low when there is a written, indefinite, non-on-call contract) — this drives the WW-Awf percentage applied.
  5. Aggregate the Collectief. Sum the ingehouden loonheffing and each premie across all Nominatief records to produce the period totals and the TotaalGenAang (total payable).
  6. Apply corrections. For a prior-period fix, emit a correction Nominatief referencing the original tijdvak; never silently overwrite.
  7. Emit the XML and validate. Build the Loonaangifte message, then run the checklist; confirm Collectief = Σ Nominatief.

Source → Loonaangifte field map

From the source → Target element
Employer loonheffingennummer LoonaangifteTijdvak/Loonheffingennummer
Tijdvak start / end date TijdvakAangifteBegindatum / TijdvakAangifteEinddatum
Total wage tax + national-insurance withheld Collectief/IngehoudenLoonbelastingPVV
Total employer premies werknemersverz. Collectief/PremieAwf + PremieAof + PremieWhk
Total Zvw employer contribution Collectief/BijdrageZvw
Total payable for the period Collectief/TotaalGeneraleAangifte
Employee BSN Nominatief/Werknemer/BurgerservicenummerWerknemer
Employee initials / surname Werknemer/Voorletters, SignificantDeelVanDeAchternaam
Date of birth Werknemer/Geboortedatum
Income-relationship number InkomstenverhoudingNr
Start of the income relationship DatumAanvangInkomstenverhouding
Code soort inkomstenverhouding CodeSoortInkomstenverhouding
Sector / sectorrisicogroep Sector / Sectorrisicogroep
Loon for loonbelasting/volksverz. LoonLoonbelastingVolksverzekeringen
Loon for werknemersverzekeringen (SV) LoonSV
Loon for Zvw LoonZvw
Withheld loonheffing IngehoudenLoonbelastingPVVTabel
Awf high/low + base AwfHoog / AwfLaag, PremieloonAWf
Aof premium (laag/hoog) base PremieloonAOFLaag / PremieloonAOFHoog
Whk premium base PremieloonWHK

Document structure

Loonaangifte                                       (root message)
└── Berichtgever                                   (the submitter — name, contact)
    └── AdministratieveEenheid
        └── LoonaangifteTijdvak
            ├── Loonheffingennummer                (NNNNNNNNNL01)
            ├── TijdvakAangifteBegindatum          (yyyy-mm-dd)
            ├── TijdvakAangifteEinddatum           (yyyy-mm-dd)
            ├── Collectief                          (period totals — exactly one)
            │   ├── IngehoudenLoonbelastingPVV
            │   ├── PremieAwf / PremieAof / PremieWhk
            │   ├── BijdrageZvw
            │   └── TotaalGeneraleAangifte
            └── Nominatief                          (one per employee, repeatable)
                └── Werknemer
                    ├── BurgerservicenummerWerknemer  (BSN)
                    ├── Voorletters / Achternaam / Geboortedatum
                    └── Inkomstenverhouding          (income relationship)
                        ├── InkomstenverhoudingNr
                        ├── CodeSoortInkomstenverhouding
                        ├── LoonLoonbelastingVolksverzekeringen
                        ├── LoonSV / LoonZvw
                        ├── IngehoudenLoonbelastingPVVTabel
                        ├── PremieloonAWf  (+ AwfHoog | AwfLaag indicator)
                        ├── PremieloonAOFLaag | PremieloonAOFHoog
                        └── PremieloonWHK

The Collectief block appears once per tijdvak; Nominatief repeats once per income relationship. A nihilaangifte carries the Collectief with zeros and no Nominatief. All amounts are integers in eurocenten.


Code tables

CodeSoortInkomstenverhouding (soort IKV, selected)

Code Meaning
11 Loon of salaris ambtenaren in de zin van de Ambtenarenwet
13 Loon of salaris directeuren van een nv/bv, wel verzekerd
15 Loon of salaris niet onder te brengen onder andere codes
18 Werknemer uitzendbureau
31 Ouderdomspensioen (AOW/pensioen)

Awf (WW-Awf) premium indicator

Indicator Meaning
AwfHoog High WW-Awf percentage — flexibele/oproep/bepaalde-tijd contracts
AwfLaag Low WW-Awf percentage — written, indefinite, non-on-call contract

Premies werknemersverzekeringen (employer-paid)

Premie Stands for
Awf Algemeen Werkloosheidsfonds (WW) — hoog or laag tarief
Aof Arbeidsongeschiktheidsfonds — Aof laag (small employer) or Aof hoog
Whk Werkhervattingskas (gedifferentieerde premie Whk)
Zvw Inkomensafhankelijke bijdrage Zorgverzekeringswet (employer)

Tijdvak (period) examples

Tijdvak Begindatum Einddatum Aangifte/betaal-datum
Maart 2026 (maand) 2026-03-01 2026-03-31 2026-04-30
Periode 03 2026 (4-weken) 2026-02-23 2026-03-22 2026-04-30

Calculation rules


Worked example (end-to-end)

Employer Voorbeeld Werkgever BV, loonheffingennummer 123456789L01, tijdvak maart 2026 (2026-03-01 → 2026-03-31), one employee: J. Jansen, BSN 111222333, born 1990-05-12, income relationship 1, soort IKV 15. Loon LB/PH €3.520,00, loon SV/Zvw €3.520,00, ingehouden loonheffing €820,00. Contract is permanent → Awf laag. Premies (already computed at the year's percentages): Awf €92,84, Aof €228,80, Whk €43,12, Zvw €232,32. Period totals equal this single employee's amounts; TotaalGeneraleAangifte = 820,00 + 92,84 + 228,80 + 43,12 + 232,32 = €1.417,08.

<?xml version="1.0" encoding="UTF-8"?>
<Loonaangifte xmlns="http://www.belastingdienst.nl/schemas/loonaangifte/2026">
  <Berichtgever>
    <Naam>Voorbeeld Werkgever BV</Naam>
    <AdministratieveEenheid>
      <LoonaangifteTijdvak>
        <Loonheffingennummer>123456789L01</Loonheffingennummer>
        <TijdvakAangifteBegindatum>2026-03-01</TijdvakAangifteBegindatum>
        <TijdvakAangifteEinddatum>2026-03-31</TijdvakAangifteEinddatum>
        <Collectief>
          <IngehoudenLoonbelastingPVV>82000</IngehoudenLoonbelastingPVV>
          <PremieAwf>9284</PremieAwf>
          <PremieAof>22880</PremieAof>
          <PremieWhk>4312</PremieWhk>
          <BijdrageZvw>23232</BijdrageZvw>
          <TotaalGeneraleAangifte>141708</TotaalGeneraleAangifte>
        </Collectief>
        <Nominatief>
          <Werknemer>
            <BurgerservicenummerWerknemer>111222333</BurgerservicenummerWerknemer>
            <Voorletters>J</Voorletters>
            <SignificantDeelVanDeAchternaam>Jansen</SignificantDeelVanDeAchternaam>
            <Geboortedatum>1990-05-12</Geboortedatum>
            <Inkomstenverhouding>
              <InkomstenverhoudingNr>1</InkomstenverhoudingNr>
              <DatumAanvangInkomstenverhouding>2018-01-01</DatumAanvangInkomstenverhouding>
              <CodeSoortInkomstenverhouding>15</CodeSoortInkomstenverhouding>
              <LoonLoonbelastingVolksverzekeringen>352000</LoonLoonbelastingVolksverzekeringen>
              <LoonSV>352000</LoonSV>
              <LoonZvw>352000</LoonZvw>
              <IngehoudenLoonbelastingPVVTabel>82000</IngehoudenLoonbelastingPVVTabel>
              <AwfLaag>J</AwfLaag>
              <PremieloonAWf>352000</PremieloonAWf>
              <PremieloonAOFLaag>352000</PremieloonAOFLaag>
              <PremieloonWHK>352000</PremieloonWHK>
            </Inkomstenverhouding>
          </Werknemer>
        </Nominatief>
      </LoonaangifteTijdvak>
    </AdministratieveEenheid>
  </Berichtgever>
</Loonaangifte>

Normalisations shown: amounts to eurocenten (€3.520,00352000, €820,0082000, €1.417,08141708); permanent contract → AwfLaag = J; Collectief/TotaalGeneraleAangifte recomputed 82000 + 9284 + 22880 + 4312 + 23232 = 141708; each Collectief total equals the sum of the single Nominatief record. This message is wrapped in the Digipoort aanlevering with PKIoverheid authentication.


Validation checklist


Last updated: 2026-06-13 — verify the current-year Belastingdienst Gegevensspecificaties Aangifte Loonheffingen (element names, code lists, Awf/Aof/Whk/Zvw percentages) and Digipoort delivery rules before use.