sepa_rator — Ruby gem for creating SEPA XML files
Successor to salesking/sepa_king (unmaintained since 2022). Adds support for newer SEPA schemas and a profile-based architecture that makes national variants (CFONB for France, DK/DFÜ for Germany, …) first-class.
Features
- Credit Transfer (
pain.001) and Direct Debit (pain.008) across 7 profile families (see table below) - Resolves the right profile from a simple
country: :frhint — falls back to generic EPC for unlisted countries - Full XSD validation on every generated XML
- Postal addresses, contact details, LEI, regulatory reporting
- Flexible charge bearer (SLEV, DEBT, CRED, SHAR)
- Mandate amendment support (original mandate ID, debtor account, creditor scheme)
pain = Payment Initiation (ISO 20022).
Supported schemas & profiles
| Family | Namespace | Country hint | Credit Transfer (pain.001) | Direct Debit (pain.008) |
|---|---|---|---|---|
| ISO (raw XSD) | Profiles::ISO |
— | SCT_03, SCT_09, SCT_13, SCT_EPC_002_03, SCT_EPC_003_03 |
SDD_02, SDD_08, SDD_12, SDD_EPC_002_02, SDD_EPC_003_02 |
| EPC SEPA | Profiles::EPC |
(SEPA fallback) | SCT_03, SCT_09, SCT_13 |
SDD_02, SDD_08, SDD_12 |
| CFONB 🇫🇷 | Profiles::CFONB |
country: :fr |
SCT_03, SCT_09, SCT_13 |
SDD_02, SDD_08, SDD_12 |
| DK / DFÜ 🇩🇪 | Profiles::DK |
country: :de |
SCT_03_GBIC3, SCT_09_GBIC5, SCT_13_GBIC5 |
SDD_02_GBIC3, SDD_08_GBIC5, SDD_12_GBIC5 |
| SPS 🇨🇭 | Profiles::SPS |
country: :ch |
SCT_03, SCT_09, SCT_13 |
SDD_02, SDD_08, SDD_12 |
| GB 🇬🇧 | Profiles::GB |
country: :gb |
SCT_03, SCT_09, SCT_13 |
SDD_02, SDD_08, SDD_12 |
| AT / PSA 🇦🇹 | Profiles::AT |
country: :at |
SCT_03, SCT_09, SCT_13 |
SDD_02, SDD_08, SDD_12 |
For the full per-profile detail (XSD, constraints, capabilities), see DOCUMENTATION.md. Adding a new country is a single file in lib/sepa_rator/profiles/ plus entries in lib/sepa_rator/profiles/country_defaults.rb.
Requirements
- Ruby 3.2+
- ActiveModel 7.0+ (tested up to 8.1)
Installation
gem 'sepa_rator', '~> 1.0'
Quick start
The simplest possible Credit Transfer
No profile, no country, no schema name — defaults to the latest EPC SEPA profile:
sct = SEPA::CreditTransfer.new(
name: 'Acme Ltd',
bic: 'BNPAFRPPXXX',
iban: 'FR7612345678901234567890123'
)
sct.add_transaction(
name: 'Supplier GmbH',
iban: 'DE21500500009876543210',
amount: 102.50,
reference: 'INV-123',
remittance_information: 'Invoice 123'
)
xml = sct.to_xml
The simplest possible Direct Debit
sdd = SEPA::DirectDebit.new(
name: 'Acme Ltd',
bic: 'BNPAFRPPXXX',
iban: 'FR7612345678901234567890123',
creditor_identifier: 'FR72ZZZ123456'
)
sdd.add_transaction(
name: 'Customer SA',
iban: 'DE21500500009876543210',
amount: 39.99,
reference: 'SUB/2025-08/001',
mandate_id: 'MND-2025-001',
mandate_date_of_signature: Date.new(2025, 1, 15)
)
xml = sdd.to_xml
The 4-level public API
sepa_rator exposes a progressive API: the simpler path covers 90 % of use
cases; the explicit path is there when you need it.
Level 0 — defaults (generic SEPA)
Do nothing special and get the latest EPC SEPA profile
(pain.001.001.13 for credit transfer, pain.008.001.12 for direct debit):
SEPA::CreditTransfer.new(name: ..., iban: ..., bic: ...)
SEPA::DirectDebit.new(name: ..., iban: ..., bic: ..., creditor_identifier: ...)
Level 1 — hint by country
The country code is the country of the bank that will receive and process your XML file — your own bank for credit transfers, the creditor's bank for direct debits. It is not the country of the beneficiary.
Example: a company with a French bank pays Italian and German suppliers. The file goes to the French bank, so write
country: :fr. The suppliers' IBANs can be from any SEPA country.
SEPA::CreditTransfer.new(country: :fr, name: ..., iban: ..., bic: ...)
# → SEPA::Profiles::CFONB::SCT_13
SEPA::DirectDebit.new(country: :de, name: ..., iban: ..., bic: ...,
creditor_identifier: ...)
# → SEPA::Profiles::DK::SDD_12_GBIC5
Countries without a dedicated profile (e.g. :it, :es, :be) fall back
to the generic EPC profile automatically.
Level 2 — country + version
If your bank hasn't upgraded to the latest ISO version yet, pin the version:
SEPA::CreditTransfer.new(country: :fr, version: :v09, ...)
# → SEPA::Profiles::CFONB::SCT_09
Supported version symbols:
| Family | Versions |
|---|---|
credit_transfer |
:v09, :v13, :latest |
direct_debit |
:v08, :v12, :latest |
Requesting an unknown version raises SEPA::UnsupportedVersionError with
the list of available versions.
The older EPC AOS schemas (pain.001.002.03, pain.001.003.03,
pain.008.002.02, pain.008.003.02) are not exposed through the
country: / version: API — use Level 3 (explicit
SEPA::Profiles::ISO::* constants) if you need them.
Level 3 — explicit profile (power user)
Pass a SEPA::Profile constant directly when you need a specific variant:
SEPA::CreditTransfer.new(
profile: SEPA::Profiles::DK::SCT_09_GBIC5,
name: ..., iban: ..., bic: ...
)
profile: is mutually exclusive with country: / version: — passing
both raises ArgumentError.
Reusing validators
class BankAccount < ActiveRecord::Base
validates_with SEPA::IBANValidator, field_name: :iban
validates_with SEPA::BICValidator, field_name: :bic
validates_with SEPA::LEIValidator, field_name: :agent_lei
end
Documentation
For the full list of options (addresses, charge bearer, amendment info, regulatory reporting, LEI, contact details, etc.), see DOCUMENTATION.md.
Changelog
See CHANGELOG.md.
Contributors
- Original contributors (salesking/sepa_king)
- sepa_rator contributors
Resources
- ISO 20022 message definitions
- EPC rulebooks
- CFONB guides
- EBICS / DK data formats
- Swiss Payment Standards (SIX)
- Bank of England ISO 20022 handbook
License
Released under the MIT License.
- Originally copyright (c) 2013-2022 Georg Leciejewski (SalesKing), Georg Ledermann.
- Copyright (c) 2025-2026 Advitam — fork, maintenance, profile-based architecture.