Home/Blog/pain.001 deep-dive: building a Swiss credit transfer file

pain.001 deep-dive: building a Swiss credit transfer file

A detailed walkthrough of the pain.001.001.09 XML structure required for submitting payment files to Swiss banks.

If your ERP generates payment files that go directly to your bank for processing — rather than having someone enter payments manually in e-banking — those files are almost certainly pain.001 XML. Pain.001 is the ISO 20022 message type for Customer Credit Transfer Initiation: the structured file you send to your bank to instruct it to make one or more outgoing payments.

Swiss banks completed their migration to ISO 20022 in 2022. The version they use for domestic Swiss franc credit transfers is pain.001.001.09 (often written as pain.001 for short). This post walks through the key parts of the XML structure, what each section does, and the Swiss-specific points that differ from the generic ISO 20022 standard.

The three-level structure

Every pain.001 file has the same three-level hierarchy:

GrpHdr (Group Header)
  └─ PmtInf (Payment Information) — one or more
         └─ CdtTrfTxInf (Credit Transfer Transaction Information) — one or more

Group Header contains information about the file as a whole: a message ID that must be unique, the creation date and time, the number of transactions in the file, and the total control sum (the sum of all payment amounts).

Payment Information groups transactions that share the same debit account, execution date, and payment method. You can have multiple PmtInf blocks in one file — for example, one block for CHF payments and another for EUR payments, or one block for today's payments and another for next week's.

Credit Transfer Transaction Information is one block per individual payment. Each block carries the payment amount, the creditor's details, and the remittance information.

Group Header in detail

<GrpHdr>
  <MsgId>PAYMENT-2024-001</MsgId>
  <CreDtTm>2024-03-15T08:30:00</CreDtTm>
  <NbOfTxs>3</NbOfTxs>
  <CtrlSum>4750.00</CtrlSum>
  <InitgPty>
    <Nm>Müller AG</Nm>
    <Id>
      <OrgId>
        <Othr>
          <Id>CHE-123.456.789</Id>
          <SchmeNm><Prtry>CHUID</Prtry></SchmeNm>
        </Othr>
      </OrgId>
    </Id>
  </InitgPty>
</GrpHdr>

The message ID must be unique — banks use it to detect duplicate file submissions. Using a combination of date, time, and a sequence number is a common approach. The NbOfTxs and CtrlSum are validation fields: if the counts and totals do not match the actual transactions in the file, the bank will reject it.

The initiating party is your company. Including the Swiss UID (CHE-123.456.789) using the CHUID scheme is standard Swiss practice.

Payment Information block

<PmtInf>
  <PmtInfId>BATCH-001</PmtInfId>
  <PmtMtd>TRF</PmtMtd>
  <NbOfTxs>3</NbOfTxs>
  <CtrlSum>4750.00</CtrlSum>
  <PmtTpInf>
    <SvcLvl><Cd>SEPA</Cd></SvcLvl>
    <LclInstrm><Prtry>IBAN</Prtry></LclInstrm>
  </PmtTpInf>
  <ReqdExctnDt><Dt>2024-03-18</Dt></ReqdExctnDt>
  <Dbtr>
    <Nm>Müller AG</Nm>
  </Dbtr>
  <DbtrAcct>
    <Id><IBAN>CH56 0483 5012 3456 7800 9</IBAN></Id>
  </DbtrAcct>
  <DbtrAgt>
    <FinInstnId><BICFI>UBSWCHZH80A</BICFI></FinInstnId>
  </DbtrAgt>
  ...
</PmtInf>

For Swiss domestic credit transfers, PmtMtd is always TRF. The local instrument (LclInstrm) should be IBAN for standard transfers. ReqdExctnDt is the requested execution date — the date you want the bank to execute the payment, not the value date at the recipient's bank.

The debtor account is your account — the account being debited. Use the full formatted IBAN with spaces as shown, or without spaces — both are accepted by Swiss banks, but without spaces is safer for machine processing.

Credit Transfer Transaction Information

This is the core of each individual payment:

<CdtTrfTxInf>
  <PmtId>
    <InstrId>PMT-001</InstrId>
    <EndToEndId>INV-2024-0047</EndToEndId>
  </PmtId>
  <Amt>
    <InstdAmt Ccy="CHF">1250.00</InstdAmt>
  </Amt>
  <CdtrAgt>
    <FinInstnId><BICFI>RAIFCH22</BICFI></FinInstnId>
  </CdtrAgt>
  <Cdtr>
    <Nm>Zulieferer GmbH</Nm>
    <PstlAdr>
      <Ctry>CH</Ctry>
      <AdrLine>Bahnhofstrasse 12</AdrLine>
      <AdrLine>8001 Zürich</AdrLine>
    </PstlAdr>
  </Cdtr>
  <CdtrAcct>
    <Id><IBAN>CH44 3199 9123 0008 8901 2</IBAN></Id>
  </CdtrAcct>
  <RmtInf>
    <Strd>
      <CdtrRefInf>
        <Tp>
          <CdOrPrtry><Cd>QRR</Cd></CdOrPrtry>
        </Tp>
        <Ref>210000000003139471430009017</Ref>
      </CdtrRefInf>
    </Strd>
  </RmtInf>
</CdtTrfTxInf>

EndToEndId is the end-to-end reference that travels with the payment through the entire chain. Swiss banks carry this through to the recipient's account statement. Using the supplier's invoice number here makes it easy to see which invoice was paid when reviewing your own bank statement. Maximum 35 characters, alphanumeric.

RmtInf (Remittance Information) is where the payment reference goes. For a QR reference, the code is QRR and the reference is the 27-digit number from the supplier's QR-bill. For an ISO creditor reference, the code is SCOR. For an unstructured reference (free text), use <Ustrd> instead of <Strd> — but unstructured remittance is less reliable for the supplier's automated reconciliation.

The QR-IBAN vs standard IBAN distinction in pain.001

If you are paying a supplier who uses a QR-IBAN, the creditor account IBAN in <CdtrAcct> is that QR-IBAN, and the remittance information must carry a QR reference (QRR). If the supplier uses a standard IBAN, use the standard IBAN and the appropriate reference type. The bank validates this consistency — a QR reference paired with a standard IBAN will be rejected.

Common rejection causes

Swiss banks run validation checks when a pain.001 file is submitted. The most common rejection reasons:

  • NbOfTxs or CtrlSum does not match the actual file content
  • Duplicate MsgId — a file with the same message ID was already processed
  • Invalid IBAN — check digit failure or account not found
  • QR reference paired with non-QR-IBAN or vice versa
  • ReqdExctnDt in the past or a bank holiday
  • Missing mandatory elements — BIC in CdtrAgt when required, missing creditor name

Your bank's pain.001 implementation guide will list the specific validation rules they apply, as Swiss banks have minor variations in what they require beyond the base standard. The pain.002 post covers how to read the status report your bank returns after processing the file.