Het SEPA XML-formaat uitgelegd: opbouw, tags en veelgemaakte fouten
2026-05-03
Een SEPA XML-bestand is het formaat dat banken verwachten als je eurobetalingen of incasso’s in een batch aanlevert. Voor een bedrijf dat leveranciers in Europa betaalt, abonnementen incasseert of salarissen uitbetaalt, wordt dat “technische” bestand al snel een operationele zaak. Eén verkeerd teken, één ontbrekend veld of één verouderde versie en de hele run staat stil.
De salarisrun heeft een deadline. Een leverancier wacht. De incassobatch moet vandaag weg, niet na drie rondes formaatcorrecties. In dit artikel lees je hoe een SEPA XML-bestand is opgebouwd, welke tags verschillen tussen overboekingen en incasso’s, welke fouten het vaakst voorkomen en hoe je een spreadsheet zonder gedoe omzet.
Wat is een SEPA XML-bestand?
SEPA XML is een gemeenschappelijke taal voor banken, gebaseerd op de internationale standaard ISO 20022. In plaats van dat elke bank een eigen formaat hanteert, zoals vroeger ClieOp03 in Nederland, gebruiken alle banken in de SEPA-zone dezelfde opbouw. Een bestand begint met een Group Header met een uniek <MsgId> van maximaal 35 tekens en een aanmaaktijdstip <CreDtTm>, gevolgd door betaalinformatie en transacties.
Twee veelgebruikte soorten
- pain.001: overboekingen, voor geld dat je verstuurt (leveranciers, salarissen, declaraties). Ook wel batchbetaling of verzamelbetaling.
- pain.008: incasso’s, voor geld dat je ophaalt bij klanten met een machtiging.
Ook als je zelf nooit XML leest, helpt het om te snappen hoe het werkt. De meeste problemen ontstaan namelijk niet in de XML, maar in de gegevens die erin gaan: de juiste velden, de juiste versie, toegestane tekens en unieke kenmerken.
De opbouw van een SEPA XML-bestand
Een SEPA XML-bestand ziet er compact uit door de geneste tags. Lees het als mappen in mappen: de buitenste map bevat het hele document, daarbinnen identificeert één deel het bestand, een ander deel groepeert gedeelde betaalgegevens en een derde deel bevat de losse transacties.

Het document
Bovenaan staat <Document>, de buitenste container. Daarbinnen zie je het soort bericht, zoals <CstmrCdtTrfInitn> voor overboekingen of <CstmrDrctDbtInitn> voor incasso’s.
Group Header
De Group Header (<GrpHdr>) is het voorblad van het bestand, met gegevens die voor het hele bestand gelden:
-
<MsgId>: het unieke kenmerk van het bestand; -
<CreDtTm>: datum en tijd van aanmaak; - samenvattende waarden zoals het aantal transacties en het controletotaal.
Vuistregel: Zie het XML-bestand als een koerierszak. De Group Header is het verzendlabel aan de buitenkant.
Payment Information
Het volgende blok is <PmtInf>. Het groepeert transacties met dezelfde context: de rekening die wordt belast of gecrediteerd, de uitvoeringsdatum, de betaalmethode. In plaats van die gegevens bij elke betaling te herhalen, staan ze één keer per groep. Wie gedeelde gegevens op het verkeerde niveau zet, krijgt afkeur, ook als de waarden zelf kloppen.
Transacties
Binnen <PmtInf> staan de afzonderlijke betalingen: <CdtTrfTxInf> bij overboekingen, <DrctDbtTxInf> bij incasso’s. Elke transactie bevat het bedrag, de ontvanger of betaler, het IBAN, de omschrijving en transactiekenmerken.
| Niveau | Functie | Voorbeeld |
|---|---|---|
| Document | Bevat het hele bericht | Eén geüpload bestand |
| Group Header | Identificeert het bestand | Berichtkenmerk, aanmaaktijd |
| Payment Information | Groepeert gedeelde batchgegevens | Rekening, uitvoeringsdatum |
| Transactie | Bevat één betaling | Eén leveranciersbetaling of één incasso |
Als mensen zeggen dat XML “streng” is, bedoelen ze vooral dat die hiërarchie gerespecteerd moet worden. De structuur is zelf onderdeel van de opdracht.
De belangrijkste tags voor overboekingen en incasso’s
| Doel | Overboeking (pain.001) | Incasso (pain.008) |
|---|---|---|
| Berichtkenmerk | <MsgId> |
<MsgId> |
| Aanmaaktijd | <CreDtTm> |
<CreDtTm> |
| Batchinformatie | <PmtInf> |
<PmtInf> |
| Transactieblok | <CdtTrfTxInf> |
<DrctDbtTxInf> |
| End-to-end-kenmerk | <EndToEndId> |
<EndToEndId> |
| Bedrag | <InstdAmt> |
<InstdAmt> |
| Machtigingsgegevens | Niet nodig |
<MndtId> en <DtOfSgntr>
|
| Incassant-ID | Niet nodig | <CdtrSchmeId> |
Overboeking: de essentie
<CdtTrfTxInf>
<PmtId>
<EndToEndId>FAC-10458</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="EUR">1250.00</InstdAmt>
</Amt>
<Cdtr>
<Nm>Industriële Leveringen BV</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>NL00BANK0000000000</IBAN>
</Id>
</CdtrAcct>
</CdtTrfTxInf>
-
<EndToEndId>is je kenmerk om de betaling te volgen. -
<InstdAmt>is het bedrag, altijd positief en met een punt als decimaalteken. Een boekhoudpakket toont uitgaande betalingen soms als negatief bedrag; in de XML hoort dat niet. -
<Nm>is de naam van de ontvanger. Let op: “Industriële” bevat een trema, dat in de praktijk vaak moet worden omgezet naar “Industriele”. -
<IBAN>is de rekening van de ontvanger.
De EPC-implementatierichtlijnen voor SEPA-overboekingen beschrijven precies hoe deze velden zijn opgebouwd.
Incasso: de essentie
<DrctDbtTxInf>
<PmtId>
<EndToEndId>CONTRIBUTIE-MEI</EndToEndId>
</PmtId>
<InstdAmt Ccy="EUR">49.00</InstdAmt>
<DrctDbtTx>
<MndtRltdInf>
<MndtId>MACHT-2024-001</MndtId>
<DtOfSgntr>2024-03-01</DtOfSgntr>
</MndtRltdInf>
</DrctDbtTx>
<Dbtr>
<Nm>Jan de Vries</Nm>
</Dbtr>
</DrctDbtTxInf>
Bij een incasso haal je geld op, dus het bestand moet aantonen dat er toestemming is:
-
<MndtId>: het machtigingskenmerk van de klant; -
<DtOfSgntr>: de datum waarop de machtiging is getekend.
Ontbreekt een van beide of klopt het niet met je administratie, dan kan het bestand technisch geldig zijn en toch later bij de bank stranden. De regels staan in de EPC-implementatierichtlijnen voor SEPA-incasso Core.
Velden die makkelijk verkeerd worden gelezen
End-to-end-ID. Dit is je transactiekenmerk, geen rekeningnummer. Gebruik iets wat je later kunt terugvinden: een factuurnummer, een salariscode of een abonnementskenmerk.
Berichtkenmerk. Het <MsgId> identificeert het hele bestand, niet één transactie. Gebruik je het opnieuw, dan kan de bank het nieuwe bestand als dubbel zien. Vooral als iemand het bestand van vorige maand kopieert en alleen de bedragen aanpast.
Veelvoorkomende controlefouten en hoe je ze oplost
Een financieel medewerker exporteert een run uit Excel, zet hem om naar XML, uploadt hem en krijgt een vage melding als “invalid schema” of “unexpected character”. De oorzaken zitten meestal in een korte lijst.

| Fout | Symptoom | Oorzaak | Oplossing |
|---|---|---|---|
| Ongeldige tekens | “Invalid character” of schemafout |
&, trema’s, slimme aanhalingstekens of regeleinden in <Nm> of omschrijving |
Tekens vóór export opschonen, spaties weghalen, tekst uit Word, pdf of e-mail controleren |
| Tijdstempel | Fout bij aanmaakdatum of berichtformaat | Verkeerd ISO-formaat of verkeerde systeemklok | ISO 8601 aanhouden, klok controleren, tijdstempels nooit met de hand aanpassen |
| Schemastructuur | “Unexpected element” of “file not compliant” | Ontbrekende bovenliggende tag, verkeerde volgorde of versie die de bank niet accepteert | Valideren tegen de juiste XSD, versie navragen bij je bank, tags niet handmatig verschuiven |
| Te lange velden | Afkeur zonder duidelijke reden | Berichtkenmerk, naam of omschrijving langer dan toegestaan | Limieten in de bron toepassen, samengestelde kenmerken splitsen |
| IBAN-fouten | Afkeur bij upload of stornering later | Ongeldig IBAN, spaties, verkeerd veld of gegevens uit verschillende bronnen | IBAN’s vooraf valideren met de IBAN-validator, naam en rekening uit hetzelfde record |
Kernpunt: Bankmeldingen beschrijven vaak het symptoom, niet de oorzaak. Eén verkeerde afsluittag kan zich als algemene schemafout voordoen.
Teams lossen controlefouten sneller op zodra ze de XML niet meer als startpunt zien. De XML is alleen de verpakking; het echte werk zit in het opschonen, koppelen en controleren van de brongegevens. Hoe je een bestand vóór het uploaden controleert, lees je in een SEPA-bestand valideren. Een incassobestand controleer je direct in de browser met de SEPA-incasso XML-validator.
Van spreadsheet naar SEPA XML
De meeste teams beginnen niet met XML, maar met een spreadsheet of CSV-export. De uitdaging is niet het invoeren van gegevens, maar het koppelen van bekende kolommen aan de juiste XML-velden.
| Kolom in je spreadsheet | Betekenis | XML-veld |
|---|---|---|
| Leverancier | Naam van de ontvanger | <Cdtr><Nm> |
| IBAN | Rekening van de ontvanger | <CdtrAcct><Id><IBAN> |
| Bedrag | Te betalen bedrag | <InstdAmt> |
| Factuurnummer | Kenmerk |
<EndToEndId> of <RmtInf>
|
| Betaaldatum | Uitvoeringsdatum | <ReqdExctnDt> |
| Machtigingskenmerk (incasso) | Toestemming van de klant | <MndtId> |
Waarom handmatig omzetten misgaat
Met de hand XML bouwen of kopiëren uit oude bestanden gaat mis op precies de punten uit de tabel hierboven: tekens, lengtes, dubbele kenmerken en verkeerde niveaus. Bovendien weet na een paar maanden niemand meer welke versie van het sjabloon klopt.
Een realistische werkwijze
- Exporteer de betaalgegevens uit je pakket naar Excel of CSV.
- Schoon namen, kenmerken en IBAN’s op.
- Koppel de kolommen eenmalig aan de SEPA-velden.
- Laat de tool IBAN’s, lengtes en verplichte velden controleren.
- Genereer het pain.001- of pain.008-bestand en upload het bij je bank.
Automatisch omzetten met GenerateSEPA
Met GenerateSEPA upload je je Excel-, CSV- of JSON-bestand, koppel je de kolommen en download je een pain.001.001.03- of pain.008.001.02-bestand. IBAN’s worden vóór het maken van het bestand gecontroleerd, en de koppeling wordt onthouden voor de volgende run. Wil je het in je eigen software inbouwen, dan gebruik je de API.
Waar het in je werkwijze past: tussen je bronbestand en je bank. Je pakket blijft de bron van de gegevens, de tool zorgt voor een geldig bestand, en jij uploadt het in je internetbankieren.
Checklist vóór het aanleveren
| Stap | Wat je controleert |
|---|---|
| 1. Soort bestand | pain.001 voor overboekingen, pain.008 voor incasso’s |
| 2. Berichtkenmerk | Uniek <MsgId>, maximaal 35 tekens |
| 3. Tijdstempel |
<CreDtTm> in ISO 8601, niet in de toekomst |
| 4. Bedragen | Positief, punt als decimaalteken, totalen kloppen |
| 5. Tekens en lengtes | Geen trema’s, & of te lange velden |
| 6. IBAN’s | Allemaal gevalideerd |
| 7. Incasso | Machtigingskenmerk, datum en incassant-ID aanwezig |
| 8. Archief | Bron- en XML-bestand samen bewaard |
Wil je je spreadsheets voortaan zonder XML-gepuzzel omzetten? Probeer GenerateSEPA 7 dagen gratis.
Veelgestelde vragen
- Wat is het SEPA XML-formaat?
- Het SEPA XML-formaat is een gestandaardiseerde digitale structuur op basis van ISO 20022 waarmee bedrijven betaalopdrachten naar hun bank sturen. De gegevens staan in geneste XML-tags die banken automatisch controleren. De twee belangrijkste soorten zijn pain.001 voor overboekingen en pain.008 voor incasso's.
- Wat is het verschil tussen pain.001 en pain.008?
- Met pain.001 verstuur je geld, bijvoorbeeld aan leveranciers of medewerkers. Met pain.008 haal je geld op van klanten via automatische incasso. Incassobestanden bevatten extra machtigingsgegevens, zoals het machtigingskenmerk en de datum van ondertekening.
- Waarom keurt de bank mijn SEPA XML-bestand af?
- Meestal door een korte lijst oorzaken: niet-toegestane tekens in namen of omschrijvingen, een verkeerd datum- of tijdformaat, te lange velden, ongeldige IBAN's of tags op de verkeerde plek. Herstel de fout in de bronspreadsheet in plaats van de XML met de hand aan te passen.
- Hoe zet je een spreadsheet om naar SEPA XML?
- Koppel elke kolom aan het juiste SEPA XML-veld, schoon de brongegevens op, controleer IBAN's en veldlengtes en genereer dan het bestand. GenerateSEPA doet dat automatisch vanuit Excel, CSV of JSON en maakt een pain.001- of pain.008-bestand.