Skip to main content
Sepa JS XML includes comprehensive validation to ensure your SEPA XML files meet all requirements. This guide covers validation options, constraints, and error handling.

Validation options

You can control validation behavior with the Options interface (from index.ts:10-26):
import { createSepaXML, type Options } from 'sepa-js-xml';

const options: Options = {
  prettyPrint: false,  // Format XML with indentation
  checkIBAN: true,     // Validate IBAN codes
  checkBIC: true       // Validate BIC codes
};

const xml = createSepaXML(sepaData, options);

Default values

From the source code (index.ts:139):
options = { 
  prettyPrint: false, 
  checkBIC: true, 
  checkIBAN: true 
}
All validation is enabled by default. You must explicitly disable it if needed.

IBAN validation

How it works

IBAN validation uses the ibantools library (from index.ts:7):
import { isValidIBAN } from "ibantools";

Enabling/disabling

const xml = createSepaXML(sepaData, {
  checkIBAN: true // Default behavior
});
The library validates all IBAN codes and throws an error if invalid.

IBAN validation errors

From the source code (index.ts:219-223), IBAN validation errors include the position index:
if (options?.checkIBAN && !isValidIBAN(item.iban)) {
  throw new Error(
    `sepaData.positions[${index}].iban is not valid (${item.iban})`,
  );
}
const xml = createSepaXML({
  id: "Test",
  creationDate: new Date(),
  initiatorName: "Test",
  positions: [{
    name: "Test",
    iban: "INVALID", // Invalid IBAN
    bic: "SSKMDEMM",
    id: "123",
    requestedExecutionDate: new Date(),
    payments: []
  }]
});
// Error: sepaData.positions[0].iban is not valid (INVALID)

Supported IBAN formats

The ibantools library supports all SEPA country IBANs:
  • DE - Germany (22 characters)
  • FR - France (27 characters)
  • IT - Italy (27 characters)
  • ES - Spain (24 characters)
  • NL - Netherlands (18 characters)
  • BE - Belgium (16 characters)
  • AT - Austria (20 characters)
AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GI, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, VA

BIC validation

How it works

BIC validation also uses ibantools (from index.ts:7):
import { isValidBIC } from "ibantools";

Enabling/disabling

const xml = createSepaXML(sepaData, {
  checkBIC: true // Default behavior
});
The library validates all BIC codes and throws an error if invalid.

BIC validation errors

From the source code (index.ts:226-230):
if (options?.checkBIC && (item.bic ? !isValidBIC(item.bic) : bicOptional)) {
  throw new Error(
    `sepaData.positions[${index}].bic is not valid (${item.bic})`,
  );
}
const xml = createSepaXML({
  id: "Test",
  creationDate: new Date(),
  initiatorName: "Test",
  positions: [{
    name: "Test",
    iban: "DE02701500000000594937",
    bic: "INVALID", // Invalid BIC
    id: "123",
    requestedExecutionDate: new Date(),
    payments: []
  }]
});
// Error: sepaData.positions[0].bic is not valid (INVALID)

BIC format

Valid BIC codes:
  • 8 characters: SSKMDEMMXXX
  • 11 characters: SSKMDEMM (branch code optional)
  • Format: AAAABBCCDDD where:
    • AAAA = Bank code
    • BB = Country code
    • CC = Location code
    • DDD = Branch code (optional)

BIC optional scenarios

From the source code (index.ts:225, index.ts:374-376), BIC is optional for:
  1. Direct debits (creditor side) - all versions
  2. Credit transfers (both sides) - PAIN version 03 only
// BIC optional - no error even with checkBIC: true
const xml = createSepaXML({
  painVersion: "pain.001.001.03",
  // ... other fields
  positions: [{
    iban: "DE02701500000000594937",
    // bic not provided - OK for version 03
    payments: [{
      iban: "DE89370400440532013000"
      // bic not provided - OK for version 03
    }]
  }]
}, {
  checkBIC: true // Still validates if BIC is provided
});

Length constraints

The library enforces maximum length constraints (from index.ts:399-403):
function checkLength(value: string, name: string, length: number) {
  if (value.length > length) {
    throw new Error(`Max length for ${name} is ${length} (${value})`);
  }
}

Field length limits

id
string
Maximum: 35 charactersApplies to:
  • sepaData.id (from index.ts:155)
  • positions[].id (from index.ts:217)
  • payments[].id (from index.ts:318-322)
name
string
Maximum: 70 charactersApplies to:
  • sepaData.initiatorName (from index.ts:156)
  • positions[].name (from index.ts:218)
  • payments[].name (from index.ts:323-327)

Length validation errors

const xml = createSepaXML({
  id: "123456789012345678901234567890123456", // 36 chars - too long!
  creationDate: new Date(),
  initiatorName: "Test",
  positions: []
});
// Error: Max length for sepaData.id is 35 (123456789012345678901234567890123456)

Error handling

Try-catch pattern

Wrap createSepaXML in a try-catch block:
import { createSepaXML } from 'sepa-js-xml';

try {
  const xml = createSepaXML({
    id: "MSG001",
    creationDate: new Date(),
    initiatorName: "My Company",
    positions: [{
      id: "PMT001",
      name: "My Company",
      iban: "DE02701500000000594937",
      bic: "SSKMDEMM",
      requestedExecutionDate: new Date(),
      payments: [{
        id: "TXN001",
        name: "Customer A",
        iban: "INVALID_IBAN",
        amount: 100.00,
        remittanceInformation: "Payment"
      }]
    }]
  });
  
  console.log("XML generated successfully");
  return xml;
  
} catch (error) {
  console.error("Validation failed:", error.message);
  // Handle the error appropriately
  // Error: sepaData.positions[0].payments[0].iban is not valid (INVALID_IBAN)
}

Common validation errors

Error: sepaData.positions[0].iban is not valid (INVALID)
Cause: IBAN fails checksum or format validationSolution: Verify IBAN with customer or use a valid IBAN from your bank
Error: sepaData.positions[0].bic is not valid (INVALID)
Cause: BIC doesn’t match expected formatSolution: Use 8 or 11 character BIC code, or omit for PAIN v03
Error: Max length for sepaData.id is 35 (very_long_identifier_that_exceeds_the_limit)
Cause: Field exceeds maximum allowed lengthSolution: Truncate the value to fit within the limit
Error: sepaData.positions[0].payments[0].end2endReference is required with the selected pain version
Cause: Using PAIN v03 without end-to-end reference (from index.ts:338-341)Solution: Add end2endReference field or use PAIN v02

Validation in tests

From the test file (index.test.ts:106-123, 125-143, 145-163):
test("check id error", () => {
  expect(() =>
    createSepaXML({
      id: "123456789123456789123456789123456789", // 36 chars
      creationDate: new Date(),
      initiatorName: "Test",
      positions: [],
    }, {
      checkIBAN: true,
      checkBIC: true,
    })
  ).toThrow(
    "Max length for sepaData.id is 35 (123456789123456789123456789123456789)"
  );
});

Validation checklist

Before generating SEPA XML:
1

Validate IBANs

Ensure all IBANs are valid for their country:
  • Correct length
  • Valid checksum
  • Proper country code
2

Validate BICs

Ensure all BICs are valid or omitted when optional:
  • 8 or 11 characters
  • Valid format
  • Optional for PAIN v03 and direct debits
3

Check field lengths

Ensure no field exceeds maximum length:
  • IDs: 35 characters
  • Names: 70 characters
4

Verify required fields

Ensure all required fields are provided:
  • end2endReference for PAIN v03 credit transfers
  • mandateId and mandateSignatureDate for direct debits
5

Test with validation enabled

Always test with default validation enabled:
createSepaXML(data) // Uses default validation

Best practices

Keep validation enabled

Always use default validation unless you have a specific reason to disable it.

Validate early

Validate IBANs and BICs when collecting user input, not just when generating XML.

Handle errors gracefully

Wrap XML generation in try-catch and provide user-friendly error messages.

Test thoroughly

Test with both valid and invalid data to ensure proper error handling.

Next steps

Examples

See complete examples with validation

Credit transfers

Learn about credit transfer requirements

Direct debits

Learn about direct debit requirements

API Reference

View complete API documentation

Build docs developers (and LLMs) love