Skip to main content
This guide walks you through creating a SEPA credit transfer XML file from scratch.

Prerequisites

Before you begin, make sure you have:
  • Node.js installed (v14 or higher recommended)
  • A JavaScript or TypeScript project set up
  • Sepa JS XML installed (see Installation)

Generate a credit transfer XML

Follow these steps to create your first SEPA credit transfer XML file:
1

Import the library

Start by importing the createSepaXML function from the package:
import { createSepaXML, type SepaData } from 'sepa-js-xml';
2

Prepare your payment data

Create a data object with your payment information. Here’s a complete example:
const paymentData: SepaData = {
  id: "MSG-001",
  creationDate: new Date(),
  initiatorName: "Your Company Name",
  positions: [
    {
      id: "BATCH-001",
      name: "Your Company Name",
      iban: "DE89370400440532013000",
      bic: "COBADEFFXXX",
      requestedExecutionDate: new Date(),
      payments: [
        {
          id: "PAYMENT-001",
          name: "John Doe",
          iban: "DE89370400440532013001",
          bic: "COBADEFFXXX",
          amount: 150.50,
          remittanceInformation: "Invoice #12345",
          end2endReference: "INV-12345"
        },
        {
          id: "PAYMENT-002",
          name: "Jane Smith",
          iban: "DE89370400440532013002",
          bic: "COBADEFFXXX",
          amount: 250.00,
          remittanceInformation: "Invoice #12346",
          end2endReference: "INV-12346"
        }
      ]
    }
  ]
};
The IBANs and BICs in this example are for demonstration only. Replace them with valid account details before generating production files.
3

Generate the XML

Call the createSepaXML function with your payment data:
const xml = createSepaXML(paymentData);

console.log(xml);
For better readability during development, you can enable pretty printing:
const xml = createSepaXML(paymentData, {
  prettyPrint: true,
  checkIBAN: true,
  checkBIC: true
});
4

Save the XML file

Write the generated XML to a file:
import { writeFileSync } from 'fs';

writeFileSync('sepa-payment.xml', xml, 'utf-8');
console.log('SEPA XML file generated successfully!');

Complete example

Here’s a complete working example that generates a SEPA credit transfer XML file:
import { createSepaXML, type SepaData } from 'sepa-js-xml';
import { writeFileSync } from 'fs';

const paymentData: SepaData = {
  id: "MSG-001",
  creationDate: new Date(),
  initiatorName: "Your Company Name",
  positions: [
    {
      id: "BATCH-001",
      name: "Your Company Name",
      iban: "DE89370400440532013000",
      bic: "COBADEFFXXX",
      requestedExecutionDate: new Date(),
      payments: [
        {
          id: "PAYMENT-001",
          name: "John Doe",
          iban: "DE89370400440532013001",
          bic: "COBADEFFXXX",
          amount: 150.50,
          remittanceInformation: "Invoice #12345",
          end2endReference: "INV-12345"
        },
        {
          id: "PAYMENT-002",
          name: "Jane Smith",
          iban: "DE89370400440532013002",
          bic: "COBADEFFXXX",
          amount: 250.00,
          remittanceInformation: "Invoice #12346",
          end2endReference: "INV-12346"
        }
      ]
    }
  ]
};

try {
  const xml = createSepaXML(paymentData, {
    prettyPrint: true,
    checkIBAN: true,
    checkBIC: true
  });
  
  writeFileSync('sepa-payment.xml', xml, 'utf-8');
  console.log('SEPA XML file generated successfully!');
} catch (error) {
  console.error('Error generating SEPA XML:', error.message);
}

Configuration options

You can customize the XML generation with these options:
OptionTypeDefaultDescription
prettyPrintbooleanfalseFormat the XML with indentation for readability
checkIBANbooleantrueValidate IBAN codes using ibantools
checkBICbooleantrueValidate BIC codes using ibantools
const xml = createSepaXML(paymentData, {
  prettyPrint: true,    // Enable formatted output
  checkIBAN: true,      // Validate IBANs (recommended)
  checkBIC: true        // Validate BICs (recommended)
});
It’s recommended to keep IBAN and BIC validation enabled in production to catch invalid account details before submitting payments to your bank.

Understanding the data structure

The SepaData interface has three main levels:

1. Message level (SepaData)

{
  id: "MSG-001",                     // Message ID (max 35 chars)
  creationDate: new Date(),          // When the message was created
  initiatorName: "Your Company",     // Your company name (max 70 chars)
  painVersion: "pain.001.001.03",    // Optional: PAIN format version
  positions: [...]                    // Array of creditor positions
}

2. Position level (CreditorPayments)

{
  id: "BATCH-001",                   // Position ID (max 35 chars)
  name: "Your Company Name",         // Debtor name (max 70 chars)
  iban: "DE89370400440532013000",    // Debtor IBAN
  bic: "COBADEFFXXX",                // Debtor BIC (optional in some versions)
  requestedExecutionDate: new Date(), // When to execute the payment
  batchBooking: true,                 // Optional: batch booking flag
  payments: [...]                     // Array of individual payments
}

3. Payment level (Payment)

{
  id: "PAYMENT-001",                 // Payment ID (max 35 chars)
  name: "John Doe",                  // Creditor name (max 70 chars)
  iban: "DE89370400440532013001",    // Creditor IBAN
  bic: "COBADEFFXXX",                // Creditor BIC (optional in some versions)
  amount: 150.50,                     // Amount in EUR
  currency: "EUR",                    // Optional: defaults to EUR
  remittanceInformation: "Invoice #12345", // Payment reference
  end2endReference: "INV-12345"      // End-to-end reference (required in pain.001.001.03)
}

Validation and error handling

The library performs automatic validation and throws errors if:
  • The id or initiatorName exceeds the maximum length
  • IBAN or BIC codes are invalid (when validation is enabled)
  • Required fields are missing for specific PAIN versions
Always wrap createSepaXML calls in a try-catch block:
try {
  const xml = createSepaXML(paymentData);
} catch (error) {
  if (error.message.includes('Max length')) {
    console.error('Field length validation failed:', error.message);
  } else if (error.message.includes('not valid')) {
    console.error('IBAN/BIC validation failed:', error.message);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

Next steps

Now that you’ve generated your first SEPA XML file, explore more advanced features:

API Reference

View detailed API documentation and type signatures

Direct Debits

Learn how to create SEPA direct debit XML files

Build docs developers (and LLMs) love