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 messaggioCreDtTm- Data/ora di creazioneNbOfTxs- Numero totale transazioniCtrlSum- Somma di controlloInitgPty- 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 bloccoPmtMtd- Metodo (TRF = Transfer)ReqdExctnDt- Data esecuzioneDbtr- Ordinante (debitore)DbtrAcct- IBAN ordinanteDbtrAgt- BIC banca ordinante
Livello 3: CdtTrfTxInf
Credit Transfer Transaction Info - La singola transazione. Può ripetersi N volte.
EndToEndId- ID end-to-endInstdAmt- Importo in EURCdtrAgt- BIC banca beneficiarioCdtr- Beneficiario (creditore)CdtrAcct- IBAN beneficiarioRmtInf- 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
NbOfTxsnel GrpHdr e nel PmtInf deve corrispondere al numero effettivo diCdtTrfTxInf - Il
CtrlSumdeve essere la somma esatta di tutti gliInstdAmt(1500.00 + 2250.00 = 3750.00) - Ogni
EndToEndIddeve essere univoco all'interno del file - Gli importi hanno sempre 2 decimali e valuta EUR
- Il
BtchBookgatruesignifica 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.
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 (&, <, >, ', "). Un beneficiario come "D&G Servizi" deve diventare D&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:
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:
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.
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:
- Carica le fatture XML (anche in blocco via ZIP) nell'area di lavoro
- Il sistema estrae automaticamente IBAN, importo, beneficiario e numero fattura
- Verifica e corregge eventuali dati mancanti o errati
- Genera il file pain.001 con tutti i namespace, header e checksum corretti
- 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
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.
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.
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.
Due livelli di attenzione. Primo: i 5 caratteri speciali XML devono essere sostituiti con le entità corrispondenti: & diventa &, < diventa <, > diventa >, ' diventa ', " diventa ". 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 gratisArticoli correlati
Prova BonificoSEPA.it
Genera file XML SEPA pain.001 dalle tue fatture elettroniche in pochi secondi.
Registrati gratis