Credit transfers allow you to send money from your account to other accounts. This guide covers everything you need to know about creating credit transfer XML files.
Basic credit transfer
Here’s a simple example of creating a credit transfer:
import { createSepaXML } from 'sepa-js-xml' ;
const xml = createSepaXML ({
painVersion: "pain.001.001.03" ,
id: "MSG001" ,
creationDate: new Date ( "2022-06-16" ),
initiatorName: "My Company" ,
positions: [{
id: "PMT001" ,
name: "My Company" ,
iban: "DE02701500000000594937" ,
bic: "SSKMDEMM" ,
requestedExecutionDate: new Date ( "2022-06-16" ),
payments: [{
id: "TXN001" ,
name: "Supplier Ltd" ,
iban: "DE89370400440532013000" ,
bic: "COBADEFFXXX" ,
amount: 150.00 ,
remittanceInformation: "Invoice payment" ,
end2endReference: "INV12345"
}]
}]
});
Required fields
Document level
The PAIN format version. Use pain.001.001.02, pain.001.003.02, pain.001.001.03, or pain.001.003.03 for credit transfers.
Unique message identifier. Maximum length: 35 characters.
When the payment file was created.
Name of the party initiating the payment. Maximum length: 70 characters.
Position level (debtor)
Unique payment information identifier. Maximum length: 35 characters.
Debtor name (your company). Maximum length: 70 characters.
Debtor IBAN (your account).
Debtor BIC. Optional for SEPA payments in versions 03.
positions[].requestedExecutionDate
When you want the payment to be executed.
Payment level (creditor)
Unique transaction identifier. Maximum length: 35 characters.
Creditor name (recipient). Maximum length: 70 characters.
Creditor IBAN (recipient account).
Creditor BIC. Optional for SEPA payments in versions 03.
Payment amount in the specified currency.
payments[].remittanceInformation
Payment description or reference information.
payments[].end2endReference
End-to-end reference. Required for pain.001.001.03 and pain.001.003.03.
Execution dates
The requestedExecutionDate determines when the bank should execute the payment:
const tomorrow = new Date ();
tomorrow . setDate ( tomorrow . getDate () + 1 );
const xml = createSepaXML ({
// ... other fields
positions: [{
// ... other fields
requestedExecutionDate: tomorrow , // Execute tomorrow
payments: [ /* ... */ ]
}]
});
Most banks require the execution date to be at least one business day in the future. Check with your bank for specific requirements.
Multiple payments
You can include multiple payments in a single position:
const xml = createSepaXML ({
painVersion: "pain.001.001.03" ,
id: "MSG001" ,
creationDate: new Date (),
initiatorName: "My Company" ,
positions: [{
id: "PMT001" ,
name: "My Company" ,
iban: "DE02701500000000594937" ,
requestedExecutionDate: new Date (),
payments: [
{
id: "TXN001" ,
name: "Supplier A" ,
iban: "DE89370400440532013000" ,
amount: 100.00 ,
remittanceInformation: "Invoice 001" ,
end2endReference: "INV001"
},
{
id: "TXN002" ,
name: "Supplier B" ,
iban: "DE89370400440532013001" ,
amount: 200.00 ,
remittanceInformation: "Invoice 002" ,
end2endReference: "INV002"
},
{
id: "TXN003" ,
name: "Supplier C" ,
iban: "DE89370400440532013002" ,
amount: 150.00 ,
remittanceInformation: "Invoice 003" ,
end2endReference: "INV003"
}
]
}]
});
Batch booking
Control whether payments are booked individually or as a batch:
Position level
Document level
const xml = createSepaXML ({
painVersion: "pain.001.001.03" ,
// ... other fields
positions: [{
// ... other fields
batchBooking: false , // Each payment booked separately
payments: [ /* ... */ ]
}]
});
Available in PAIN version 03 only. Controls booking at the position level. const xml = createSepaXML ({
painVersion: "pain.001.001.02" ,
batchBooking: true , // All payments in one booking
// ... other fields
positions: [ /* ... */ ]
});
Available in PAIN version 02 only. Controls booking at the document level.
Batch booking (true) : All payments appear as a single entry on your account statement with the total amount.Individual booking (false) : Each payment appears as a separate entry on your account statement.Default value is true.
Different currencies
While SEPA primarily uses EUR, you can specify other currencies:
const xml = createSepaXML ({
painVersion: "pain.001.001.02" ,
// ... other fields
positions: [{
// ... other fields
payments: [
{
id: "TXN001" ,
name: "US Supplier" ,
iban: "DE89370400440532013000" ,
bic: "COBADEFFXXX" ,
amount: 100.00 ,
currency: "USD" , // Specify currency
remittanceInformation: "Payment in USD"
}
]
}]
});
Most SEPA payments must be in EUR. Non-EUR currencies may be rejected by your bank. Check with your bank before using other currencies.
BIC requirements
The BIC (Bank Identifier Code) requirements vary by PAIN version:
BIC is required for both debtor and creditor: positions : [{
bic: "SSKMDEMM" , // Required
payments: [{
bic: "COBADEFFXXX" // Required
}]
}]
BIC is optional for both debtor and creditor: positions : [{
iban: "DE02701500000000594937" ,
// bic is optional
payments: [{
iban: "DE89370400440532013000"
// bic is optional
}]
}]
From the source code (index.ts:293-295, index.ts:381-383): BIC is optional for pain.001.001.03 and pain.001.003.03. The library automatically handles missing BIC codes for these versions.
End-to-end reference
The end-to-end reference tracks payments throughout the payment chain:
payments : [{
id: "TXN001" ,
end2endReference: "INV-2024-12345" , // Optional in v02, required in v03
// ... other fields
}]
End-to-end reference is optional .
End-to-end reference is required . From the source code (index.ts:337-341), an error is thrown if missing: Error: sepaData.positions[0].payments[0].end2endReference is required with the selected pain version
Complete example
Here’s a complete credit transfer with all features:
import { createSepaXML } from 'sepa-js-xml' ;
const xml = createSepaXML ({
painVersion: "pain.001.001.03" ,
id: "MSG20240316001" ,
creationDate: new Date ( "2024-03-16T10:30:00" ),
initiatorName: "Acme Corporation Ltd" ,
positions: [{
id: "BATCH001" ,
name: "Acme Corporation Ltd" ,
iban: "DE02701500000000594937" ,
batchBooking: false ,
requestedExecutionDate: new Date ( "2024-03-17" ),
payments: [
{
id: "PAY001" ,
name: "Office Supplies Inc" ,
iban: "DE89370400440532013000" ,
amount: 1250.50 ,
currency: "EUR" ,
remittanceInformation: "Office supplies - Invoice OS-2024-0315" ,
end2endReference: "OS20240315"
},
{
id: "PAY002" ,
name: "Tech Solutions GmbH" ,
iban: "DE89370400440532013001" ,
amount: 3500.00 ,
currency: "EUR" ,
remittanceInformation: "Software license renewal Q2 2024" ,
end2endReference: "SW20240316"
}
]
}]
}, {
prettyPrint: true ,
checkIBAN: true ,
checkBIC: true
});
console . log ( xml );
Next steps
Direct debits Learn how to collect payments with direct debits
PAIN versions Compare all PAIN format versions
Validation Understand validation and error handling
Examples View more real-world examples