Multi-message files
Send a whole file of SWIFT MT messages in one convert request: paged MT940 statements consolidate into one statement, N MT103s become one bulk pacs.008, and camt batch entries can be split per transaction.
One request, many FIN messages
A bank export often holds more than one MT (SWIFT FIN) message: a long statement split into pages, a day's worth of statements for several accounts, or a run of outgoing payments. POST /v1/convert accepts such a file as one message body. The file can contain up to 1000 messages, in any of these shapes:
- Enveloped messages back to back:
{1:...}{2:...}{4:...-}repeated. - Bare text blocks, each starting with a
:20:line. A lone-line between messages (common in statement exports) is accepted. - A mix of both. Blank lines and whitespace between messages are ignored.
The whole file must fit the normal request body limit, and MT input is capped at 1 MiB.
Which formats accept a file
| Source | What happens to N messages |
|---|---|
mt940, mt950 | Pages of the same statement are chained into one statement (see below); separate statements stay separate |
mt942 | One statement per message. Each interim report's totals belong to that message, so reports are never merged |
mt900, mt910 | One notification per message |
mt103 | One payment per message; to pacs.008 they become one bulk document |
mt202, mt205 | One payment per message; to pacs.009 they become one bulk document |
mt101 | Read as one :28D: message chain, rendered as one pain.001 |
mt104 | One pain.008 whose batches are the messages' batches, in order |
mt103-rejt, mt202-rejt | One pacs.002 status report with one transaction status per message |
Every other MT source accepts exactly one message. A second message is invalid-input 400 with the parser code mt.multiple_messages in detail. Investigation-style messages (MT192, MT195, MT196 and their 2xx twins) copy fields of the original message, :20: included, so their files can't be split safely.
More than 1000 messages is invalid-input 400 with the code mt.too_many_messages. If one message in the file fails to parse, the detail names it ("message 3 of 12"), with line numbers counted inside that message.
Paged MT940 statements
MT messages are limited in size, so banks split a long statement into pages. Each page repeats the account (:25:) and the statement number in :28C:, and the page number after the slash goes up by one: 00042/001, 00042/002, and so on.
Send the pages together and transmute consolidates them into one statement:
curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?to=camt.053" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
--data-binary @- <<'EOF'
{1:F01AAAADEFFXXXX0000000000}{2:I940BBBBDEFFXXXXN}{4:
:20:STMT0001
:25:DE89370400440532013000
:28C:00042/001
:60F:C260601EUR1000,00
:61:2606020602C250,00NTRFNONREF//BANKREF1
:86:INVOICE 4711
:62M:C260602EUR1250,00
-}
{1:F01AAAADEFFXXXX0000000000}{2:I940BBBBDEFFXXXXN}{4:
:20:STMT0001
:25:DE89370400440532013000
:28C:00042/002
:60M:C260602EUR1250,00
:61:2606030603D80,00NTRFNONREF//BANKREF2
:86:INVOICE 4712
:62F:C260603EUR1170,00
-}
EOF
{
"result": "<?xml version="1.0" ... <Stmt><Id>STMT0001</Id> ... <Ntry>...250.00...</Ntry><Ntry>...80.00...</Ntry></Stmt> ...",
"warnings": [
{ "code": "MISSING_REQUIRED_DEFAULTED", "severity": "info", "sourceField": "statement[0].createdAt", "targetField": "GrpHdr/CreDtTm", "...": "..." },
{ "code": "MISSING_REQUIRED_DEFAULTED", "severity": "info", "sourceField": "statement[0].createdAt", "targetField": "Stmt[0]/CreDtTm", "...": "..." }
],
"meta": {
"detectedType": "mt940",
"detectedVersion": null,
"targetType": "camt.053.001.08",
"durationMs": 3,
"inputMessages": 2
}
}
The result is one Stmt with both entries. The rules:
- Opening balance comes from the first page's
:60F:; closing balance from the last page's:62F:. The intermediate:62M:/:60M:balances are checked against each other (a mismatch is anAMOUNT_MISMATCHwarning) and then discarded. - Entries are kept in page order.
- Pages are grouped in the order you send them. They are never sorted or merged across a gap.
- A page with a different account or statement number starts a new statement with no warning. Several statements in one file become several
Stmtblocks in one camt.053 (or several MT messages for an MT target). - A page that repeats the previous page's account and statement number but doesn't continue its sequence (a missing page, a duplicate, or pages out of order) starts a new statement and adds the warning
mt.28c_chain_gap(severitywarning,sourceField:28C:). If you see it, check the file for a missing page before you trust the balances.
MT942 interim reports carry the same :28C: numbering. They are checked for gaps the same way, but each report stays its own statement.
N MT103s to one pacs.008
A file of customer transfers converts to a single pacs.008 with one CdtTrfTxInf per MT103:
curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?to=pacs.008" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
--data-binary @payments.fin
GrpHdr/NbOfTxsis the message count. No total amount is computed for the group header.- The group header values come from the first message. When a later message has a different reference, it's reported as
DROP_FIELD(that reference still travels as the transaction'sInstrId). A different reimbursement agent is reported asDROP_AGENT. - A file containing a return (an MT103 or MT202 with
/RETN/in:72:) is rejected. Convert returns on their own withfrom=mt103-retnorfrom=mt202-retn.
MT202 and MT205 files work the same way and produce one pacs.009.
The reverse direction needs no special input: one pacs.008 with N transactions converts to N MT103 messages, returned as an array in result with meta.pages set.
meta.inputMessages
meta.inputMessages appears on /v1/convert responses only when the request carried more than one FIN message. Its value is the number of messages read. A multi-message file is still one request and one usage unit. To send many independent messages and get a result per message, use Batch.
Splitting camt batch entries (debulk)
ISO 20022 statements (camt.053, camt.052, camt.054) can book several payments as one entry: a single Ntry with one amount and several TxDtls (transaction details) underneath. By default transmute maps such an entry to one transaction. It keeps the first TxDtls and reports the rest as a lossy DROP_FIELD.
Set options.debulk (or ?debulk=true on raw requests) to get one transaction per TxDtls instead:
curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?to=mt940&debulk=true" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: application/xml" \
--data-binary @statement.camt053.xml
A batch entry of 1250.00 with three transaction details (500.00, 450.00, 300.00) then becomes three :61: lines instead of one:
:61:2606020602C500,00NTRFE2E-BATCH-1//BANK-BATCH-1
:86:RENT JUNE FLAT 1
:61:2606020602C450,00NTRFE2E-BATCH-2//BANK-BATCH-1
:86:RENT JUNE FLAT 2
:61:2606020602C300,00NTRFE2E-BATCH-3//BANK-BATCH-1
:86:RENT JUNE FLAT 3
How it works:
- Each transaction's amount is copied from its own
TxDtls/AmtDtls/TxAmt, never calculated. Booking and value date, status, direction, the bank's reference and the bank transaction code are shared from the entry. References, counterparty and remittance come from eachTxDtls. - A successful split adds
ENTRY_DEBULKED(info; the detail gives the transaction count). - If any
TxDtlsof the entry has noTxAmt, the entry is not split. It stays one transaction, as withoutdebulk, and you getDEBULK_AMOUNT_MISSING(warning). - The copied amounts must be in the entry's currency, match its credit/debit direction and add up exactly to the entry amount. Otherwise the entry is not split and you get
AMOUNT_MISMATCH. A split entry therefore always balances against the statement.
debulk defaults to false, and output without it is unchanged. It applies to synchronous /v1/convert. Batch items don't carry it.
All codes above are listed in the warning registry.