Pain.008.001.02 voorbeeld: SEPA-incassobestand in XML uitgelegd
2026-05-06
Het is de laatste werkdag van de maand. De incassorun moet vandaag naar de bank, want de cashflow van volgende week hangt ervan af. Je uploadt het bestand in de zakelijke omgeving van ING of Rabobank en krijgt een korte foutmelding terug waar je weinig mee kunt. In een teksteditor ziet de XML er prima uit, maar de bank accepteert hem niet.
Meestal ligt dat niet aan “XML in het algemeen”, maar aan pain.008 in het bijzonder: het berichtformaat waarmee je SEPA-incasso’s bij je bank aanlevert. Een voorbeeldbestand van een forum kopiëren helpt dan zelden. Je moet weten welke gegevens in welk blok horen, hoe de totalen worden berekend en welke regels je bank bovenop het schema controleert.
In dit artikel vind je een compleet pain.008.001.02 voorbeeld met Nederlandse voorbeeldgegevens, uitleg per XML-blok, een mappingtabel vanuit Excel of CSV en de fouten waarop banken het vaakst afkeuren.
Waarom je incassobestand werd afgekeurd
Het patroon is bijna altijd hetzelfde. De administratie exporteert een Excel-bestand, iemand plakt waarden in een sjabloon, de XML wordt gegenereerd en de bank weigert het bestand met een schemafout, een melding over de machtiging of een probleem met de rekening van de betaler. Het bestand kan goed gevormde XML zijn en toch fout voor de bank.
Afgekeurde bestanden zijn bijna altijd terug te voeren op een van deze vier oorzaken:
- Rekeninggegevens slecht geëxporteerd: Excel heeft voorloopnullen weggehaald, IBAN’s staan als getal in plaats van als tekst of er zitten spaties in.
-
Totalen kloppen niet:
NbOfTxsenCtrlSumsluiten niet aan op de transactieregels, bijvoorbeeld na filteren of afronden. - Machtigingsgegevens onvolledig: er staat een bedrag en een IBAN, maar het machtigingskenmerk of de datum van ondertekening ontbreekt.
- Schema-proof, maar niet bank-proof: het bestand voldoet aan het ISO-schema, maar niet aan de aanvullende regels van je bank.
Kernpunt: banken keuren veel bestanden af die technisch geldige XML zijn, maar als betaalopdracht niet kloppen.
Voor finance is dat geen detail. Elke afgekeurde run schuift je ontvangsten op en betekent handwerk onder tijdsdruk: totalen opnieuw controleren, bestand opnieuw maken, opnieuw uploaden. Gebeurt dat vaker, dan is het geen tikfout meer maar een procesprobleem.
Wat is een pain.008.001.02-bestand?
Een pain.008.001.02-bestand is een ISO 20022-bericht van het type Customer Direct Debit Initiation. Simpel gezegd: het XML-formaat waarmee een bedrijf zijn bank opdracht geeft om geld via SEPA-incasso bij betalers te innen. Voor overboekingen bestaat een apart bericht, pain.001. Wil je meer achtergrond over de standaard zelf, lees dan wat ISO 20022 is.
Zie het bestand als een contract tussen je brongegevens en de verwerkingssoftware van je bank. Het vertelt de bank:
- wie de incassant is (naam, IBAN, incassant-ID);
- welke batch je aanlevert en op welke datum moet worden geïncasseerd;
- welke machtiging bij elke incasso hoort;
- welk bedrag bij welke betaler moet worden afgeschreven;
- welke omschrijving de betaler op zijn afschrift ziet.
In Nederland verving SEPA-incasso in 2014 de oude binnenlandse incasso en het ClieOp03-formaat. Heb je nog oude exportbestanden in dat formaat, lees dan hoe je ClieOp03 omzet naar SEPA XML. Het voordeel van XML is dat de betekenis van elk veld expliciet is, in plaats van verstopt in vaste posities. Met <RmtInf><Ustrd> kun je bovendien een duidelijke omschrijving meegeven die het afletteren eenvoudiger maakt.
De structuur van een pain.008-bestand
Lees het bestand als een hiërarchie. Bovenaan staat het XML-element Document, daarbinnen één incassobericht, daaronder één groepsheader, een of meer batches en per batch de afzonderlijke incasso’s.

| Niveau | XML-blok | Wat het regelt |
|---|---|---|
| 1 | Document |
De container en de namespace |
| 2 | CstmrDrctDbtInitn |
Het incassobericht zelf |
| 3 | GrpHdr |
Kenmerk en totalen van het hele bestand |
| 4 | PmtInf |
Een batch incasso’s met dezelfde instellingen |
| 5 | DrctDbtTxInf |
Eén incasso bij één betaler |
GrpHdr is de envelop: die identificeert het bestand als geheel. PmtInf is de werkbatch: splits je incasso’s op datum, op Core of B2B, op sequentietype of op rekening van de incassant, dan maak je aparte PmtInf-blokken. DrctDbtTxInf bevat per betaler de naam, het IBAN, het bedrag, het machtigingskenmerk en de omschrijving.
Vuistregel: geldt een waarde voor elke regel in de batch, zet hem dan op batchniveau. Verschilt hij per betaler, dan hoort hij in
DrctDbtTxInf.
Het volledige pain.008.001.02 voorbeeld
Hieronder staat een compleet pain.008.001.02 voorbeeld met twee incasso’s. Alle gegevens zijn fictief: NL91ABNA0417164300 is het bekende voorbeeld-IBAN, de andere IBAN’s en het incassant-ID hebben alleen een geldig controlegetal. Gebruik het als structuurmodel en vul je eigen gegevens in.
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02">
<CstmrDrctDbtInitn>
<!-- Groepsheader: identificeert het hele bestand -->
<GrpHdr>
<MsgId>INC20260115001</MsgId>
<CreDtTm>2026-01-15T10:30:00</CreDtTm>
<NbOfTxs>2</NbOfTxs>
<CtrlSum>245.50</CtrlSum>
<InitgPty>
<Nm>Voorbeeld Diensten B.V.</Nm>
</InitgPty>
</GrpHdr>
<!-- Betalingsinformatie: gedeelde instellingen voor deze batch -->
<PmtInf>
<PmtInfId>BATCH-20260120-RCUR</PmtInfId>
<PmtMtd>DD</PmtMtd>
<NbOfTxs>2</NbOfTxs>
<CtrlSum>245.50</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>RCUR</SeqTp>
</PmtTpInf>
<ReqdColltnDt>2026-01-20</ReqdColltnDt>
<Cdtr>
<Nm>Voorbeeld Diensten B.V.</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>NL91ABNA0417164300</IBAN>
</Id>
</CdtrAcct>
<CdtrAgt>
<FinInstnId>
<BIC>ABNANL2A</BIC>
</FinInstnId>
</CdtrAgt>
<ChrgBr>SLEV</ChrgBr>
<CdtrSchmeId>
<Id>
<PrvtId>
<Othr>
<Id>NL69ZZZ123456780000</Id>
<SchmeNm>
<Prtry>SEPA</Prtry>
</SchmeNm>
</Othr>
</PrvtId>
</Id>
</CdtrSchmeId>
<!-- Eerste incasso -->
<DrctDbtTxInf>
<PmtId>
<EndToEndId>FACT-10001</EndToEndId>
</PmtId>
<InstdAmt Ccy="EUR">120.50</InstdAmt>
<DrctDbtTx>
<MndtRltdInf>
<MndtId>MACHT-10001</MndtId>
<DtOfSgntr>2025-11-01</DtOfSgntr>
</MndtRltdInf>
</DrctDbtTx>
<DbtrAgt>
<FinInstnId>
<BIC>INGBNL2A</BIC>
</FinInstnId>
</DbtrAgt>
<Dbtr>
<Nm>Bakkerij De Molen</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>NL38INGB1234567806</IBAN>
</Id>
</DbtrAcct>
<RmtInf>
<Ustrd>Factuur FACT-10001 januari</Ustrd>
</RmtInf>
</DrctDbtTxInf>
<!-- Tweede incasso -->
<DrctDbtTxInf>
<PmtId>
<EndToEndId>FACT-10002</EndToEndId>
</PmtId>
<InstdAmt Ccy="EUR">125.00</InstdAmt>
<DrctDbtTx>
<MndtRltdInf>
<MndtId>MACHT-10002</MndtId>
<DtOfSgntr>2025-11-15</DtOfSgntr>
</MndtRltdInf>
</DrctDbtTx>
<DbtrAgt>
<FinInstnId>
<BIC>RABONL2U</BIC>
</FinInstnId>
</DbtrAgt>
<Dbtr>
<Nm>Studio Noord V.O.F.</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>NL13RABO1234567806</IBAN>
</Id>
</DbtrAcct>
<RmtInf>
<Ustrd>Factuur FACT-10002 januari</Ustrd>
</RmtInf>
</DrctDbtTxInf>
</PmtInf>
</CstmrDrctDbtInitn>
</Document>
Wat dit voorbeeld goed doet:
-
Eén uniek bestandskenmerk:
MsgIdkomt maar één keer voor en wordt niet hergebruikt. -
Kloppende totalen:
NbOfTxs(2) enCtrlSum(€ 245,50) staan in de groepsheader en in de batch, en komen overeen met de twee transacties. -
Gedeelde waarden op batchniveau: incassodatum, incassant, incassant-ID en type (
CORE,RCUR) staan inPmtInf. -
Machtigingsgegevens per transactie:
MndtId(het machtigingskenmerk) enDtOfSgntrstaan in elkeDrctDbtTxInf. -
Leesbare omschrijving:
Ustrdbevat een korte tekst die de betaler herkent.
Wijkt je eigen bestand op een van deze punten sterk af, begin dan daar met zoeken.
Pain.008-velden per blok uitgelegd
De snelste manier om een pain.008-bestand te debuggen is weten welke velden structureel zijn, welke operationeel en welke bankspecifiek. Een overzicht van alle verplichte velden vind je in het helpartikel over verplichte velden in pain.008.001.02.
Declaratie en groepsheader
Het bestand begint met de XML-declaratie in UTF-8 en een Document met de namespace van pain.008.001.02. Per document is er één CstmrDrctDbtInitn.
| Veld | Functie | Formaatregel |
|---|---|---|
MsgId |
Kenmerk van het hele bestand | Uniek, geen spaties |
CreDtTm |
Aanmaakmoment |
JJJJ-MM-DDTuu:mm:ss, met hoofdletter T
|
NbOfTxs |
Aantal transacties | Moet gelijk zijn aan het aantal regels |
CtrlSum |
Totaalbedrag | Som van alle InstdAmt, punt als decimaalteken |
Hergebruik je een MsgId, dan kan de bank het bestand als dubbel aanmerken. CreDtTm faalt vaker op opmaak dan op inhoud.
Batchvelden in PmtInf
-
PmtInfIdidentificeert de batch, niet alleen het bestand. -
PmtMtdis bij incasso altijdDD. -
LclInstrm/CdisCOREvoor consumenten en de meeste bedrijven, ofB2Bvoor de zakelijke incasso. Het verschil lees je in Core of B2B. -
SeqTpgeeft aan of het een eerste (FRST), doorlopende (RCUR), laatste (FNAL) of eenmalige (OOFF) incasso is. -
ReqdColltnDtis de gewenste incassodatum voor de hele batch. -
CdtrSchmeIdbevat je incassant-ID. Twijfel je over het formaat, controleer het dan met de incassant-ID-tool.
Transactievelden die acceptatie bepalen
In elke DrctDbtTxInf doen deze velden het werk: EndToEndId (je eigen referentie, terug te vinden bij storneringen), InstdAmt met het attribuut Ccy="EUR", MndtId en DtOfSgntr, Dbtr en DbtrAcct voor naam en IBAN van de betaler en RmtInf/Ustrd voor de omschrijving (maximaal 140 tekens). Probeer in die omschrijving niet je hele factuuradministratie te proppen: kort en consequent werkt het best.
Nederlandse banken werken met implementatierichtlijnen die via Betaalvereniging Nederland zijn afgestemd, en elke bank publiceert daarnaast een eigen formaatbeschrijving. Houd ook de SEPA-tekenset aan: tekens als &, # of letters met accenten kunnen tot afkeur leiden.
Van Excel of CSV naar pain.008 XML
Bijna niemand begint met XML. Je begint met een export uit je boekhoudpakket, facturatiesysteem of ERP. Het lastige is niet het schrijven van tags, maar bepalen waar elke kolom in de structuur thuishoort. In een bestand met één regel per incasso zitten twee soorten gegevens door elkaar: batchgegevens (incassant, IBAN, incassodatum) en transactiegegevens (betaler, machtigingskenmerk, bedrag, factuurnummer).
| Kolom in Excel/CSV | pain.008-element | Niveau | Let op |
|---|---|---|---|
| Bestandskenmerk | MsgId |
GrpHdr | Uniek per bestand |
| Batchkenmerk | PmtInfId |
PmtInf | Uniek per batch |
| Incassodatum | ReqdColltnDt |
PmtInf | Gelijk voor de hele batch |
| Naam en IBAN incassant |
Cdtr/Nm, CdtrAcct/Id/IBAN
|
PmtInf | Vast per batch |
| Naam klant | Dbtr/Nm |
DrctDbtTxInf | Eén per regel |
| IBAN klant | DbtrAcct/Id/IBAN |
DrctDbtTxInf | Als tekst opslaan, vooraf valideren |
| Bedrag | InstdAmt |
DrctDbtTxInf | Punt als decimaalteken in de XML |
| Machtigingskenmerk | MndtId |
DrctDbtTxInf | Moet overeenkomen met de getekende machtiging |
| Datum ondertekening | DtOfSgntr |
DrctDbtTxInf | Alleen datum |
| Factuurnummer |
EndToEndId en/of Ustrd
|
DrctDbtTxInf | Kies één vaste regel |
Wat in de praktijk werkt: leg de kolomnamen vroeg vast, houd batchconstanten apart van de regels, bepaal eenmalig waar het factuurnummer heen gaat en controleer IBAN’s met de IBAN-validator voordat je converteert. Fouten in de spreadsheet komen anders gewoon mee in de XML. Een uitgebreidere uitleg staat in CSV omzetten naar SEPA XML.
Veelvoorkomende pain.008-fouten en hoe je ze oplost
Een afkeurmelding toont meestal het symptoom, niet de oorzaak.

Schemafouten. Verkeerde namespace, een veld op de verkeerde plek, een ontbrekende declaratie of een verkeerde codering. Een geldig veld in het verkeerde blok faalt nog steeds. Deze fouten vang je af met een schemacontrole vóór het uploaden, bijvoorbeeld met de gratis SEPA-incasso XML-validator.
Controletotalen. De klassieker:
| Symptoom | Waarschijnlijke oorzaak | Oplossing |
|---|---|---|
NbOfTxs klopt niet |
Rijen verborgen of verwijderd na het tellen | Opnieuw tellen op de definitieve export |
CtrlSum klopt niet |
Afronding of gefilterde rijen | Optellen op basis van de geëxporteerde bedragen |
| Batch- en bestandstotaal verschillen | Meerdere batches inconsistent verwerkt | Na het groeperen op beide niveaus herberekenen |
Verkeerde typecodes. LclInstrm moet CORE of B2B zijn en overeenkomen met je incassocontract en met de machtiging. Een B2B-incasso op een Core-machtiging, of andersom, wordt geweigerd.
Machtiging of rekening. Een ontbrekend MndtId of DtOfSgntr, een IBAN dat niet bestaat of verborgen tekens uit Excel. Komt de incasso pas na verwerking terug, dan zie je een redencode zoals MD01 (geen geldige machtiging) of AC04 (rekening opgeheven).
Een vaste testvolgorde helpt: bronregels valideren, XML genereren, tegen het schema controleren, één regel handmatig nalopen en pas dan uploaden. Meer daarover in een SEPA-bestand valideren.
Pain.008 genereren met GenerateSEPA
Wil je de XML niet met de hand bouwen, dan is een converter met visuele mapping de praktische route.

Met GenerateSEPA upload je je Excel-, CSV- of JSON-bestand, koppel je de kolommen aan de SEPA-velden (naam, IBAN, bedrag, machtigingskenmerk, omschrijving) en genereer je een pain.008.001.02-bestand voor Core of B2B. De IBAN’s worden gecontroleerd voordat het bestand wordt gemaakt, en de mapping wordt onthouden voor de volgende keer. Controleer voor het downloaden toch altijd de kenmerken (niet hergebruikt van een oude run), de incassodatum, de machtigingsgegevens en de omschrijvingen.
Staan de incassogegevens al in je eigen software, dan is de API de logischere keuze. Je systeem stuurt de gegevens van incassant, batch en transacties als JSON en krijgt het incassobestand terug, zonder dat iemand iets overtypt. Dat loont vooral bij terugkerende facturatie, als meerdere mensen aan de gegevens werken of als je elke run in je eigen systeem wilt kunnen terugvinden. Een technische uitwerking vind je in SEPA XML via een API.

Checklist voor je volgende incassobestand
| Stap | Wat je doet | Wanneer |
|---|---|---|
| 1 | IBAN’s en machtigingskenmerken in de bron controleren | Voor elke run |
| 2 | Batchgegevens scheiden van transactiegegevens | Bij het inrichten |
| 3 | Unieke MsgId, PmtInfId en EndToEndId gebruiken |
Bij elke export |
| 4 |
CORE/B2B en SeqTp per batch controleren |
Bij elke run |
| 5 | Totalen herberekenen en het bestand valideren | Vlak voor het uploaden |
Een pain.008-bestand is geen tekstdocument dat je onder tijdsdruk bewerkt, maar het eindproduct van een gestructureerd gegevensproces. Controleer je volgende bestand eerst in de SEPA-incasso XML-validator voordat het naar je bank gaat.
Veelgestelde vragen
- Waarvoor gebruik je een pain.008.001.02-bestand?
- Een pain.008.001.02-bestand is een ISO 20022-bericht waarmee je je bank opdracht geeft om SEPA-incasso's uit te voeren. Het bevat je gegevens als incassant, de instellingen per batch, de machtigingsgegevens en per betaler het bedrag en de omschrijving. Je uploadt het in de zakelijke omgeving van je bank.
- Waarom keurt mijn bank een pain.008-bestand af dat technisch klopt?
- Een algemene XML-controle kijkt alleen naar structuur en syntax. Je bank controleert daarnaast bedrijfsregels, zoals een geldig incassant-ID, kloppende controletotalen, de juiste code voor Core of B2B en volledige machtigingsgegevens. Een bestand kan dus goed gevormde XML zijn en toch worden afgekeurd.
- Hoe zet ik Excel-gegevens om naar pain.008-velden?
- Splits je gegevens in batchgegevens (naam en IBAN van de incassant, incassodatum) en transactiegegevens (naam en IBAN van de betaler, bedrag, machtigingskenmerk, datum van ondertekening). Koppel elke kolom aan het XML-veld op het juiste niveau en valideer de IBAN's voordat je het bestand genereert.
- Welke pain.008-fouten komen het vaakst voor?
- De klassiekers zijn een ongeldig IBAN, een NbOfTxs of CtrlSum die niet overeenkomt met de transacties, een verkeerde code in LclInstrm en ontbrekende machtigingsgegevens zoals het machtigingskenmerk of de datum van ondertekening. Ook tekens die je bank niet accepteert in namen of omschrijvingen leiden vaak tot afkeur.