XML SEPA pain.001: Esempio Completo Commentato Riga per Riga

Se lavori con i pagamenti bancari tramite file, prima o poi ti troverai davanti a un file XML SEPA pain.001. Questo formato, definito dallo standard ISO 20022, è il modo in cui banche e aziende si scambiano istruzioni di pagamento nell'area SEPA. In questo articolo analizziamo la struttura completa di un file pain.001.001.03 con un esempio reale commentato riga per riga, i campi obbligatori e opzionali, gli errori più comuni e come validare il file prima di inviarlo alla banca.

Indice

Cos'è il formato pain.001.001.03

Il pain.001.001.03 (Payment Initiation - Customer Credit Transfer Initiation, versione 03) è un formato XML definito dallo standard internazionale ISO 20022. È il formato utilizzato per trasmettere istruzioni di bonifico SCT (SEPA Credit Transfer) dalle aziende alle banche.

Il nome "pain" sta per PAyment INitiation, "001" identifica il tipo di messaggio (Credit Transfer), e "001.03" indica la versione dello schema. In Italia, questa è la versione adottata da tutte le banche aderenti al circuito CBI e al sistema SEPA.

Perché esiste questo standard

Prima della SEPA, ogni paese europeo aveva il proprio formato per i pagamenti bancari. L'ISO 20022 ha unificato tutto: un'azienda italiana può generare un file pain.001 e inviarlo a una banca tedesca, francese o spagnola con la stessa struttura XML.

Lo standard copre 36 paesi dell'area SEPA, tutte le valute EUR, e supporta sia bonifici singoli che distinte con centinaia di transazioni.

Il file pain.001 viene tipicamente generato da un software gestionale, un ERP, o uno strumento dedicato come BonificoSEPA.it, e poi importato nell'home banking per l'autorizzazione e l'invio dei pagamenti.

Struttura del file XML SEPA

Un file pain.001.001.03 è organizzato in 3 livelli gerarchici, ciascuno con un ruolo specifico:

Livello 1: GrpHdr

Group Header - L'intestazione del messaggio. Compare una sola volta per file.

  • MsgId - ID univoco del messaggio
  • CreDtTm - Data/ora di creazione
  • NbOfTxs - Numero totale transazioni
  • CtrlSum - Somma di controllo
  • InitgPty - Chi inizia il pagamento

Livello 2: PmtInf

Payment Information - Il blocco pagamento. Contiene i dati dell'ordinante e la data di esecuzione.

  • PmtInfId - ID del blocco
  • PmtMtd - Metodo (TRF = Transfer)
  • ReqdExctnDt - Data esecuzione
  • Dbtr - Ordinante (debitore)
  • DbtrAcct - IBAN ordinante
  • DbtrAgt - BIC banca ordinante

Livello 3: CdtTrfTxInf

Credit Transfer Transaction Info - La singola transazione. Può ripetersi N volte.

  • EndToEndId - ID end-to-end
  • InstdAmt - Importo in EUR
  • CdtrAgt - BIC banca beneficiario
  • Cdtr - Beneficiario (creditore)
  • CdtrAcct - IBAN beneficiario
  • RmtInf - Causale del bonifico

La relazione tra i livelli è: un file contiene un GrpHdr e uno o più PmtInf. Ogni PmtInf contiene una o più CdtTrfTxInf (transazioni). In pratica, la maggior parte dei file ha un solo blocco PmtInf con tutte le transazioni dentro.

Esempio completo di file XML

Ecco un file pain.001.001.03 completo e funzionante con 2 bonifici. Ogni riga è commentata per spiegare il suo ruolo. Puoi usare questo esempio come base per i tuoi test o per capire cosa genera il tuo software.

<!-- Dichiarazione XML standard -->
<?xml version="1.0" encoding="UTF-8"?>

<!-- Elemento radice con namespace ISO 20022 per pain.001.001.03 -->
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <CstmrCdtTrfInitn>  <!-- Customer Credit Transfer Initiation -->

    <!-- ============================================= -->
    <!-- LIVELLO 1: GROUP HEADER (intestazione file)    -->
    <!-- ============================================= -->
    <GrpHdr>
      <MsgId>BONSEPA-2026032901</MsgId>          <!-- ID univoco del messaggio (max 35 char) -->
      <CreDtTm>2026-03-29T10:30:00</CreDtTm>     <!-- Data e ora di creazione (ISO 8601) -->
      <NbOfTxs>2</NbOfTxs>                       <!-- Numero totale di bonifici nel file -->
      <CtrlSum>3750.00</CtrlSum>                 <!-- Somma di tutti gli importi (1500 + 2250) -->
      <InitgPty>                                  <!-- Initiating Party: chi crea il file -->
        <Nm>Rossi Consulting SRL</Nm>             <!-- Nome/ragione sociale (max 70 char) -->
      </InitgPty>
    </GrpHdr>

    <!-- ============================================= -->
    <!-- LIVELLO 2: PAYMENT INFORMATION (blocco pag.)  -->
    <!-- ============================================= -->
    <PmtInf>
      <PmtInfId>PMT-2026032901</PmtInfId>       <!-- ID univoco del blocco pagamento -->
      <PmtMtd>TRF</PmtMtd>                       <!-- Metodo: TRF = Credit Transfer -->
      <BtchBookg>true</BtchBookg>                 <!-- true = addebito unico, false = singoli -->
      <NbOfTxs>2</NbOfTxs>                       <!-- Numero transazioni in questo blocco -->
      <CtrlSum>3750.00</CtrlSum>                 <!-- Somma importi di questo blocco -->
      <PmtTpInf>                                  <!-- Payment Type Information -->
        <SvcLvl>                                  <!-- Service Level -->
          <Cd>SEPA</Cd>                           <!-- Codice servizio: SEPA -->
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>2026-03-31</ReqdExctnDt>     <!-- Data esecuzione richiesta (YYYY-MM-DD) -->
      <Dbtr>                                      <!-- Debtor: chi paga (ordinante) -->
        <Nm>Rossi Consulting SRL</Nm>             <!-- Ragione sociale ordinante -->
      </Dbtr>
      <DbtrAcct>                                  <!-- Conto dell'ordinante -->
        <Id>
          <IBAN>IT60X0542811101000000123456</IBAN> <!-- IBAN ordinante (27 char per Italia) -->
        </Id>
      </DbtrAcct>
      <DbtrAgt>                                   <!-- Banca dell'ordinante -->
        <FinInstnId>
          <BIC>BPMOIT22XXX</BIC>                <!-- Codice BIC/SWIFT (8 o 11 char) -->
        </FinInstnId>
      </DbtrAgt>

      <!-- ============================================= -->
      <!-- LIVELLO 3: TRANSAZIONE 1 - Bonifico fornitore -->
      <!-- ============================================= -->
      <CdtTrfTxInf>
        <PmtId>                                   <!-- Identificativi del pagamento -->
          <EndToEndId>E2E-FT2026-0042</EndToEndId> <!-- ID end-to-end (tracciabile, max 35) -->
        </PmtId>
        <Amt>                                      <!-- Importo del bonifico -->
          <InstdAmt Ccy="EUR">1500.00</InstdAmt>   <!-- Importo con valuta EUR (2 decimali) -->
        </Amt>
        <CdtrAgt>                                  <!-- Banca del beneficiario -->
          <FinInstnId>
            <BIC>UNCRITMMXXX</BIC>              <!-- BIC banca beneficiario -->
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>                                     <!-- Creditor: beneficiario -->
          <Nm>Forniture Ufficio SPA</Nm>           <!-- Nome beneficiario (max 70 char) -->
        </Cdtr>
        <CdtrAcct>                                 <!-- Conto del beneficiario -->
          <Id>
            <IBAN>IT40S0300203280284975661141</IBAN> <!-- IBAN beneficiario -->
          </Id>
        </CdtrAcct>
        <RmtInf>                                   <!-- Remittance Info: causale -->
          <Ustrd>Pagamento fattura FT-2026-0042</Ustrd> <!-- Causale non strutturata (max 140) -->
        </RmtInf>
      </CdtTrfTxInf>

      <!-- ============================================= -->
      <!-- LIVELLO 3: TRANSAZIONE 2 - Bonifico consulente -->
      <!-- ============================================= -->
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>E2E-FT2026-0089</EndToEndId> <!-- ID diverso per ogni transazione -->
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">2250.00</InstdAmt>   <!-- Secondo importo -->
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BIC>BCITITMM</BIC>                 <!-- BIC Intesa Sanpaolo -->
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>Marco Bianchi</Nm>                  <!-- Beneficiario persona fisica -->
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>IT15T0306901783100000300159</IBAN> <!-- IBAN secondo beneficiario -->
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>Compenso consulenza marzo 2026 - FT-2026-0089</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>

    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

Punti chiave dell'esempio

  • Il NbOfTxs nel GrpHdr e nel PmtInf deve corrispondere al numero effettivo di CdtTrfTxInf
  • Il CtrlSum deve essere la somma esatta di tutti gli InstdAmt (1500.00 + 2250.00 = 3750.00)
  • Ogni EndToEndId deve essere univoco all'interno del file
  • Gli importi hanno sempre 2 decimali e valuta EUR
  • Il BtchBookg a true significa addebito unico sul conto (non uno per ogni bonifico)

Campi obbligatori vs opzionali

Non tutti i campi dello schema pain.001.001.03 sono obbligatori. La tabella seguente elenca i campi principali con il loro XPath, obbligatorietà e descrizione.

Campo XPath Obbl. Descrizione
MsgId GrpHdr/MsgId Sì Identificativo univoco del messaggio (max 35 caratteri)
CreDtTm GrpHdr/CreDtTm Sì Data e ora di creazione in formato ISO 8601
NbOfTxs GrpHdr/NbOfTxs Sì Numero totale di transazioni nel file
CtrlSum GrpHdr/CtrlSum Opz. Somma di controllo degli importi (consigliato)
InitgPty/Nm GrpHdr/InitgPty/Nm Sì Nome di chi inizia il pagamento
PmtInfId PmtInf/PmtInfId Sì ID univoco del blocco pagamento
PmtMtd PmtInf/PmtMtd Sì Metodo pagamento: TRF per bonifici
BtchBookg PmtInf/BtchBookg Opz. Batch booking: true = addebito unico
ReqdExctnDt PmtInf/ReqdExctnDt Sì Data esecuzione richiesta (YYYY-MM-DD)
Dbtr/Nm PmtInf/Dbtr/Nm Sì Nome dell'ordinante (debitore)
DbtrAcct/IBAN PmtInf/DbtrAcct/Id/IBAN Sì IBAN del conto dell'ordinante
DbtrAgt/BIC PmtInf/DbtrAgt/FinInstnId/BIC Opz. BIC/SWIFT della banca ordinante
EndToEndId CdtTrfTxInf/PmtId/EndToEndId Sì ID univoco end-to-end della transazione
InstdAmt CdtTrfTxInf/Amt/InstdAmt Sì Importo con attributo Ccy="EUR"
CdtrAgt/BIC CdtTrfTxInf/CdtrAgt/FinInstnId/BIC Opz. BIC della banca beneficiario
Cdtr/Nm CdtTrfTxInf/Cdtr/Nm Sì Nome del beneficiario (max 70 char)
CdtrAcct/IBAN CdtTrfTxInf/CdtrAcct/Id/IBAN Sì IBAN del beneficiario
RmtInf/Ustrd CdtTrfTxInf/RmtInf/Ustrd Opz. Causale del bonifico (max 140 char)

Nota importante

Anche se il CtrlSum e il BIC sono tecnicamente opzionali nello schema XSD, molte banche italiane li richiedono. Il consiglio è di includerli sempre per evitare rifiuti in fase di importazione.

Errori comuni nella generazione XML

Se il file viene rifiutato dalla banca o non supera la validazione, il problema è quasi sempre uno di questi:

1. Namespace sbagliato o mancante

L'elemento <Document> deve avere esattamente il namespace urn:iso:std:iso:20022:tech:xsd:pain.001.001.03. Un errore di battitura, un namespace di versione diversa (es. pain.001.001.09) o l'assenza completa del namespace causano il rifiuto immediato.

Errato: <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
Corretto: <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">

2. CtrlSum non corrispondente

Il valore di CtrlSum deve essere la somma esatta (con 2 decimali) di tutti gli InstdAmt contenuti nel file. Se aggiungi o rimuovi una transazione senza aggiornare il CtrlSum, la banca rifiuta il file. Lo stesso vale per il NbOfTxs: deve corrispondere al numero effettivo di elementi CdtTrfTxInf.

3. IBAN malformato

L'IBAN deve essere in formato compatto (senza spazi): IT60X0542811101000000123456, non IT60 X054 2811 1010 0000 0123 456. Deve superare la validazione del checksum (cifre di controllo in posizione 3-4). Un IBAN con checksum errato viene rifiutato sia in fase di validazione XSD che dalla banca.

4. Data di esecuzione nel passato

Il campo ReqdExctnDt (data di esecuzione richiesta) non può essere nel passato. Alcune banche accettano la data odierna solo se il file viene caricato entro il cut-off (tipicamente le 16:00-17:00). Se invii una distinta con data di ieri, verrà rifiutata.

5. Caratteri speciali non escapati

I caratteri &, <, >, ' e " devono essere sostituiti con le entità XML corrispondenti (&amp;, &lt;, &gt;, &apos;, &quot;). Un beneficiario come "D&G Servizi" deve diventare D&amp;G Servizi nell'XML. Se usi una libreria XML standard, l'escaping avviene automaticamente.

Come validare il file XML

Prima di importare il file nella banca, è fondamentale validarlo. Ecco i 3 livelli di validazione:

1

Validazione XSD (schema)

Lo schema XSD ufficiale del pain.001.001.03 definisce la struttura, i tipi di dato e i vincoli di cardinalità. La validazione contro l'XSD verifica che il file sia sintatticamente corretto. Puoi scaricare l'XSD dal sito ISO 20022 e usare un validatore XML come xmllint:

xmllint --schema pain.001.001.03.xsd mio_file.xml --noout
2

Validazione logica

Lo schema XSD non cattura tutti gli errori. Serve una validazione aggiuntiva che verifichi: la corrispondenza tra NbOfTxs e il numero effettivo di transazioni, la correttezza del CtrlSum, la validità dei codici IBAN (algoritmo di checksum), il formato dei codici BIC, e che la data di esecuzione non sia nel passato.

3

Test di importazione in banca

Alcune banche (Intesa Sanpaolo, UniCredit, BNL) offrono un ambiente di test o un'anteprima dell'importazione che mostra gli errori senza eseguire i pagamenti. Se la tua banca lo supporta, è il modo più affidabile per verificare la compatibilità del file. In alternativa, puoi creare un file con un importo minimo (es. 0.01 EUR) come test, caricarlo e poi cancellarlo prima dell'autorizzazione.

Tool online per la validazione

Esistono diversi strumenti online gratuiti per validare file XML contro uno schema XSD: FreeFormatter.com, XMLValidation.com e Liquid XML Studio (versione gratuita). Attenzione: se il file contiene dati reali (IBAN, nomi), valuta i rischi di privacy prima di caricarli su servizi terzi. Per la massima sicurezza, usa xmllint in locale.

Generare automaticamente il file XML

Costruire manualmente un file pain.001 è possibile ma impratico, soprattutto con molte transazioni. Ecco come automatizzare il processo.

Con BonificoSEPA.it (dalle fatture elettroniche)

BonificoSEPA.it genera automaticamente file pain.001.001.03 a partire dalle fatture elettroniche XML ricevute dai fornitori:

  1. Carica le fatture XML (anche in blocco via ZIP) nell'area di lavoro
  2. Il sistema estrae automaticamente IBAN, importo, beneficiario e numero fattura
  3. Verifica e corregge eventuali dati mancanti o errati
  4. Genera il file pain.001 con tutti i namespace, header e checksum corretti
  5. Scarica il file pronto per l'importazione nel tuo home banking

Il file generato è validato contro lo schema XSD e compatibile con tutte le banche italiane ed europee. Il piano gratuito include 3 distinte al mese.

Con librerie di programmazione

Se preferisci una soluzione custom, esistono librerie open-source per i principali linguaggi:

Linguaggio Libreria Note
PHP digitick/sepa-xml La più usata per generare pain.001 e pain.008 in PHP
Python python-sepa Supporta pain.001.001.03 con API semplice
Java j-easy/jsepa Generazione e parsing di file ISO 20022
C# / .NET SepaWriter NuGet package per Credit Transfer e Direct Debit
JavaScript sepa-js Genera pain.001 lato client o Node.js

Domande frequenti

Quale versione di pain.001 devo usare?

In Italia lo standard adottato dalla quasi totalità delle banche è pain.001.001.03. Questa versione è conforme alle linee guida CBI (Corporate Banking Interbancario) e garantisce la massima compatibilità. Le versioni successive (04, 05, 09) esistono ma non sono ancora largamente supportate nel sistema bancario italiano. Se devi interagire con banche di altri paesi SEPA, verifica quale versione accettano, ma la 03 resta la scelta più sicura.

Il file XML va firmato digitalmente?

No, il file XML pain.001 non richiede firma digitale. Il file viene caricato nell'home banking come file di testo XML, e l'autorizzazione al pagamento avviene attraverso i meccanismi di sicurezza della banca: OTP via SMS/app, token hardware, o firma digitale CBI. La firma è quindi gestita a livello di canale bancario, non a livello di file. Questo vale per tutte le banche italiane.

Posso inserire più di 1000 bonifici in un file?

Lo standard ISO 20022 non impone un limite al numero di transazioni per file. Tuttavia, molte banche italiane applicano limiti pratici che variano da istituto a istituto. Tipicamente il range è tra 500 e 5000 transazioni per file. Intesa Sanpaolo e UniCredit accettano fino a circa 5000 transazioni, mentre banche più piccole o BCC possono avere limiti inferiori (500-1000). Se devi inviare molti bonifici, la soluzione è spezzare il file in più distinte. Verifica sempre con la tua banca il limite specifico.

Come gestisco i caratteri speciali nell'XML?

Due livelli di attenzione. Primo: i 5 caratteri speciali XML devono essere sostituiti con le entità corrispondenti: & diventa &amp;, < diventa &lt;, > diventa &gt;, ' diventa &apos;, " diventa &quot;. Secondo: lo standard SEPA accetta solo il set di caratteri Latin definito dalla EPC (European Payments Council), che include lettere A-Z, numeri 0-9, spazi, e pochi simboli come / - ? : ( ) . , +. Caratteri come accenti gravi, tilde, @, e simboli speciali vanno rimossi o sostituiti prima di inserirli nel file.

Genera file XML SEPA pain.001 in automatico

Carica le fatture elettroniche XML e ottieni il file pain.001.001.03 validato, pronto per l'importazione nel tuo home banking.

Registrati gratis

Articoli correlati

Conversione SEPA XML: come convertire fatture in file XML per bonifici Leggi Bonifico prioritario XML SEPA: cos'è e come generarlo Leggi Bonifici multipli da Excel: come creare distinte SEPA da foglio di calcolo Leggi

Prova BonificoSEPA.it

Genera file XML SEPA pain.001 dalle tue fatture elettroniche in pochi secondi.

Registrati gratis