Skip to content

National variants

Some countries use national extensions of the SEPA ISO 20022 schemas under different XML namespaces. These are distinct from bank profiles: a profile is additive on top of a given schema, while a national variant is a different XML schema with its own namespace, element ordering, and element names.

sepa-xml-ts supports the German DK (DFU agreement Anlage 3) variants:

VariantSchemaNamespace
pain.001.003.03German DK Credit Transferurn:iso:std:iso:20022:tech:xsd:pain.001.003.03
pain.008.003.02German DK Direct Debiturn:iso:std:iso:20022:tech:xsd:pain.008.003.02

Both ship with their official XSD (vendored in the package) and are verified against it in CI.

German DK credit transfer: pain.001.003.03

Section titled “German DK credit transfer: pain.001.003.03”

The model input is the same CreditTransferDocument as for pain.001.001.09. Pass { variant: 'pain.001.003.03' } to emit and validate against the DK schema.

import { writeCreditTransfer, type CreditTransferDocument } from 'sepa-xml-ts'
import { validateXsd } from 'sepa-xml-ts/xsd'
const xml = writeCreditTransfer(doc, { variant: 'pain.001.003.03' })
// <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03">...
const xsdResult = await validateXsd(xml)
console.log(xsdResult.valid) // true -- validates against the DK XSD

Structural differences from pain.001.001.09

Section titled “Structural differences from pain.001.001.09”
Elementpain.001.001.09pain.001.003.03
ReqdExctnDt<ReqdExctnDt><Dt>YYYY-MM-DD</Dt></ReqdExctnDt><ReqdExctnDt>YYYY-MM-DD</ReqdExctnDt>
Financial institution ID<BICFI> element<BIC> element
DbtrAgt when no BICOmittedRequired: <Othr><Id>NOTPROVIDED</Id></Othr>
CdtrAgt when no BICEmpty placeholderOmitted

The NOTPROVIDED fallback in DbtrAgt is the only allowed placeholder in the DK XSD when the debtor’s BIC is unknown. The writer handles this automatically.

parse() auto-detects the namespace and reads a DK credit transfer file into a CreditTransferDocument. The returned parsed.type is 'pain.001' in both cases.

import { parse } from 'sepa-xml-ts'
const parsed = parse(dkXml)
// parsed.type === 'pain.001'
// parsed.data is a CreditTransferDocument

The model input is the same DirectDebitDocument as for pain.008.001.08. Pass { variant: 'pain.008.003.02' } to emit and validate against the DK SDD schema.

import { writeDirectDebit } from 'sepa-xml-ts'
import { validateXsd } from 'sepa-xml-ts/xsd'
const xml = writeDirectDebit(doc, { variant: 'pain.008.003.02' })
// <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02">...
const xsdResult = await validateXsd(xml)
console.log(xsdResult.valid) // true

Structural differences from pain.008.001.08

Section titled “Structural differences from pain.008.001.08”
Elementpain.008.001.08pain.008.003.02
Financial institution ID<BICFI> element<BIC> element
CdtrAgt when no BICEmpty placeholder<Othr><Id>NOTPROVIDED</Id></Othr>
DbtrAgt when no BICEmpty placeholder<Othr><Id>NOTPROVIDED</Id></Othr>
GrpHdr/CtrlSumRequiredOmitted (optional in DK XSD)

parse() reads a DK direct debit file into a DirectDebitDocument. The returned parsed.type is 'pain.008' in both cases.

pain.001.001.03 is not a national variant, it is the older ISO 20022 credit transfer format (pre-2014 EPC). It is exposed through the same variant option for systems that still require .03 on the wire (for example an existing bank integration that has not moved to .09).

import { writeCreditTransfer } from 'sepa-xml-ts'
const xml = writeCreditTransfer(doc, { variant: 'pain.001.001.03' })
// <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">...

The model input is the same CreditTransferDocument as for .09. Structural differences from pain.001.001.09: a plain ReqdExctnDt element (no Dt wrapper), the BIC element instead of BICFI, and a debtor FinInstnId that is emitted (empty when no BIC is set). The output is verified against the official schemas/iso20022/pain.001.001.03.xsd and round-trips through parse(). By default writeCreditTransfer still emits the modern pain.001.001.09.

The variant and profile options are independent and work together:

import { writeCreditTransfer, requireBic } from 'sepa-xml-ts'
const xml = writeCreditTransfer(doc, {
variant: 'pain.001.003.03',
profile: requireBic,
})

The profile check runs against the validated model. The variant controls the serialization.

  • National variants for countries other than Germany are not currently shipped. Adding a new variant requires the official XSD and golden test samples as verification oracles.
  • German DK variants for pain.002 (status reports) and camt.* messages are out of scope.