MT940 - SWIFT format
Describes how MT940 SWIFT bank statement files are structured, how messages and tags are parsed, and which fields are extracted or ignored when importing transactions.
Use this topic to determine whether an MT940 file delivered by your bank is supported, what data is extracted, and what is ignored.
Background: How an MT940 file is structured
MT940 is a SWIFT message format for bank statement delivery. A single file can contain one or more messages, each representing a complete statement for one bank account. Messages are plain text, tag-based, and delimited by the :20: tag that begins each new message.
:20: REFERENCE123 ← starts a new message (transaction reference)
:25: NWBKGB2L/12345678 ← bank account number
:28C: 00001/001 ← statement number / sequence (not stored)
:60F: C260401GBP000000000 ← opening balance — currency extracted here
:61: 260401C1500,00NCHK... ← one transaction (statement line)
:86: PAYMENT FROM ACME LTD ← narrative for the preceding :61:
:61: 260402C2000,00NMSC... ← next transaction
:86: INVOICE 12345
:62F: C260402GBP003500,00 ← closing balance (not stored)
:20: REFERENCE456 ← second message begins here (new account)
...How to identify an MT940 file
Each message begins with a :20: tag. Tags follow the format :nn: or :nnX: (colon, digits, optional letter, colon). If the file does not contain :20: lines, no messages will be parsed and the result will be empty.
Amount encoding
MT940 uses a comma as the decimal separator (European convention). For example, 1500,00 = 1500.00. This is different from BAI2 which uses integer encoding.
Date format
yyMMdd (2-digit year). Value date from :61: is the primary date; entry date (MMDD) is a fallback if the value date fails to parse.
File structure: Tag reference
:20: Transaction Reference Number
Used: Yes → splits messages
:25: / :25P: Account Identification
Used: Yes → account number
Logic: Keep value after last / (strip BIC prefix)
:28C: Statement / Sequence
Used: No
:60F: / :60M: Opening Balance
Used: Yes → currency only
Extract from characters 8–10
:61: Statement Line
Used: Yes → core transaction parsing
:86: Narrative
Used: Yes → description
Priority over :61: reference
:62F: / :62M: Closing Balance
Used: No
[1] Value date (yyMMdd) → Primary date
[2] Entry date (MMdd) → Fallback date
[3] D/C mark (C, D, RC, RD) → Filter
Keep: C, RC
Skip: D, RD
[4] Funds code → Ignored
[5] Amount → Parsed (, → .)
[6] Transaction type code → Used for filtering
[7] Account owner reference → Fallback reference
[8] Bank reference (//...) → Primary reference
Reference number
Bank reference (//...) → Primary
Account owner reference → Fallback
Description
:86: narrative → Primary
:61: reference → Fallback
What is and is not extracted
Extracted fields
Bank account number → :25: / :25P: (value after last /)
Transaction amount → :61: [5] (comma → decimal)
Currency → :60F: / :60M: (chars 8–10)
Value date → :61: [1] (yyMMdd)
Bank reference → :61: (//...)
Account owner reference → :61: [7] (fallback)
Transaction type code → :61: [6] (e.g., NCHK)
Narrative / description → :86: (multi-line)
Raw data → Full :61: block preserved
Not extracted / ignored
Debit transactions → Skipped (D, RD)
Opening balance amount → Not stored (currency only from :60F:)
Closing balance → :62F: / :62M: ignored
Statement number → :28C: ignored
Transaction reference → :20: used only for splitting
Entry date → Only fallback (not stored directly)
Funds code → Ignored (positional only)
BIC from :25P: → Ignored
Multi-message files
A single MT940 file can carry statements for multiple bank accounts in sequence. Each :20: tag starts a fresh message with its own account number (:25:) and currency (:60F:). The parser processes all messages and returns all transactions as a single flat list. There is no limit on the number of messages per file.
Configuration parameters
allowed_transaction_type_codes: Whitelist of :61: transaction type codes (e.g. NCHK, NMSC). If configured, transactions with codes not in this list are skipped. If the list is empty or null, all credit transactions are accepted.
remove_preceding_zeroes_from_bank_account_no: Strips leading zeros from the account number extracted from :25:
Note:MT940 has no configuration for FX rates, bank charges, detail type code mapping, or custom field mapping. These are Citibank BAI2-specific features.
Behaviors to be aware of
1. Only credit transactions are extracted.Any :61: line where the D/C mark is D (debit) or RD (reversal of debit) is silently skipped. If you expect debit transactions to appear in the system, they will not — this is by design.
2. Currency comes from the opening balance, not the transaction.The :60F: tag provides the account currency and it applies to every transaction in that message. If a transaction involves a foreign currency, that is not reflected — only the account's statement currency is stored.
3. Transactions with malformed :61: lines are skipped.If a :61: line is too short to contain a value date, or the amount cannot be parsed, the transaction is logged as a warning and excluded from results. The rest of the file continues processing.
4. Value date fallback.If the value date (yyMMdd) cannot be parsed, the parser falls back to the entry date (MMDD). If neither is parseable, a ParseException is thrown and the entire file fails.
5. Account number extraction strips the BIC prefix.:25: lines often include a BIC or bank code followed by / and then the account number (e.g., NWBKGB2L/12345678). Only the portion after the last / is kept as the account number.