Files & FormatsPayment Spreadsheets

Payment spreadsheets

Turn a CSV or XLSX sheet of payments into an MT101 or pain.001 credit transfer: sending the file, mapping your column headers, amounts, dates, batching and limits.

A sheet of payments in, a payment file out

Payment runs often start life as a spreadsheet. Two source formats read them:

Format idInputConverts to
csv-paymentsCSV text, UTF-8, delimiter , ; or tab (detected from the header row)pain.001, mt101
xlsx-paymentsan Excel workbook; the first sheet is readpain.001, mt101

pain.001 is the ISO 20022 customer credit transfer initiation, and mt101 is its MT counterpart. Spreadsheets are never auto-detected because any sheet could be anything, so from is required. Without it the response is unsupported-format 422, telling you to set from to csv-payments or xlsx-payments.

curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?from=csv-payments&to=pain.001" \
  -H "Authorization: Bearer $TRANSMUTE_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @- <<'EOF'
creditor_name,creditor_iban,amount,currency,execution_date,debtor_name,debtor_iban,remittance
EXAMPLE LTD,GB29NWBK60161331926819,1250.00,EUR,2026-06-09,EXAMPLE GMBH,DE89370400440532013000,INVOICE 1001
EOF

The result is a pain.001.001.09 with one payment batch for the debtor DE89370400440532013000, executing on 2026-06-09, holding one 1250.00 EUR transfer to EXAMPLE LTD. Required values the sheet doesn't carry, such as the message id, are defaulted and reported with MISSING_REQUIRED_DEFAULTED.

Sending the file

FormHow
Raw CSVContent-Type: text/csv, options as query parameters
Raw XLSXContent-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, --data-binary @payments.xlsx
JSON envelopemessage holds the CSV text; for XLSX, message is the base64 of the workbook and messageEncoding is "base64"
File uploadthe file as the file part of a multipart/form-data request, with from, to and options as form fields

Mapping your headers

A header row is required. Each header is matched case-insensitively, with spaces, hyphens and dots treated like _. It is resolved in this order:

  1. your options.columnMap,
  2. the default header names below,
  3. the target path spelled out (creditor.name).

columnMap maps your header to a path, or to ignore to skip the column silently:

{
  "from": "csv-payments",
  "to": "mt101",
  "message": "Payee;Payee IBAN;Betrag;Currency;Execution Date;Notes
...",
  "options": {
    "columnMap": { "Payee": "creditor.name", "Payee IBAN": "creditor.iban", "Betrag": "amount", "Notes": "ignore" },
    "numberFormat": "comma"
  }
}

On raw requests, pass it as a JSON object string: ?columnMap={"Payee":"creditor.name","Betrag":"amount"} (URL-encoded).

PathDefault headersLevel
msgIdmsg_id, message_idfile
initiatingParty.nameinitiating_partyfile
paymentInfoIdpayment_info_id, batch_idbatch
executionDateexecution_date, payment_datebatch
debtor.namedebtor_namebatch
debtor.iban, debtor.accountdebtor_iban, debtor_accountbatch
debtor.bicdebtor_bicbatch
endToEndIdend_to_end_id, referencepayment
instrIdinstruction_idpayment
uetruetrpayment
amountamountpayment
currencycurrency, ccypayment
creditor.namecreditor_name, beneficiary_name, payeepayment
creditor.iban, creditor.accountcreditor_iban, beneficiary_iban, creditor_account, beneficiary_accountpayment
creditor.biccreditor_bic, beneficiary_bicpayment
creditor.address.street, .buildingNumber, .postCode, .town, .countrycreditor_street, creditor_building_number, creditor_postcode, creditor_town or creditor_city, creditor_countrypayment
intermediary.bicintermediary_bicpayment
remittanceremittance, remittance_info, memopayment (one remittance line per line break in the cell)
purposepurpose, purpose_codepayment
chargeBearercharge_bearer, chargespayment (DEBT, CRED, SHAR, SLEV, or OUR, BEN, SHA)
fxContractReffx_contract_refpayment
exchangeRateexchange_ratepayment
originalAmount, originalCurrencyoriginal_amount, original_currencypayment

amount, currency and creditor.name are required. A column that matches nothing is ignored and reported with COLUMN_UNMAPPED (info). The warning's sourceField is columns[N] (the column position), and it never quotes your header text or cell values.

These are invalid-input 400: a missing required column, two columns resolving to the same path, or an unknown path in columnMap.

Amounts and dates

  • Amounts. options.numberFormat sets the separators for the whole file: point (default, 1,234.56) or comma (1.234,56). It is never guessed per cell. Spaces and apostrophes are removed. A zero or negative amount, more decimals than the currency allows, or any other character is a 400 naming the row number and the path, never the cell. Excel stores numbers with a decimal point, so xlsx-payments rejects comma.
  • Dates. YYYY-MM-DD (optionally with a time), YYYYMMDD and YYYY/MM/DD are always accepted. Day/month layouts need options.dateFormat: dmy accepts DD/MM/YYYY, DD.MM.YYYY and DD-MM-YYYY; mdy accepts MM/DD/YYYY. An ambiguous date without dateFormat is rejected, never guessed. Excel date cells are read as dates.

Batching

Rows that share the same payment info id, execution date and debtor details form one batch, in the order they first appear. File-level values such as msgId come from the first row that has them. A different value in a later row is dropped with a lossy DROP_FIELD naming the row.

An MT101 needs an execution date. A sheet without one converts to pain.001 but not to mt101 (400).

Limits

LimitValue
Data rows50,000
Columns256
Bytes per cell4096
EncodingUTF-8 (a leading byte-order mark is ignored)
XLSXfirst sheet only; workbooks over the size limits fail with workbook exceeds a size limit

The request body limit of /v1/convert applies to the file. Empty rows are skipped, and a row with values in columns beyond the header is rejected.

columnMap and numberFormat apply to synchronous /v1/convert; batch items don't carry them. All warning codes are in the warning registry.