Skip to content
SWIFT MT ↔ ISO 20022

Convert SWIFT MT to ISO 20022 in one API call

A stateless, API-first service that converts SWIFT MT messages to and from ISO 20022, normalizes either format to clean JSON, and validates at selectable strictness. Message bodies arenever persisted and never logged — completing a request leaves behind exactly one row of usage metadata.

Free tier: 1,000 conversions / month · no card required.

0 bodies
stored or logged

Message contents live in request-scoped memory only. The database keeps metadata: type, size, duration, status, warning codes.

≤ 24h
the only two exceptions

Idempotency cache (24h TTL) and the encrypted async batch store (purged on completion; TTL ≤ 24h). Nothing else touches payload content.

EU-only
single region

All processing and backups stay in the EU. Statelessness makes right-to-erasure trivial — for payloads there is nothing to erase.

Capabilities

Everything the conversion engine actually does

Grounded in the real product surface — every card maps to a documented endpoint or feature, not a roadmap promise.

MT ↔ ISO 20022

Convert SWIFT MT statements and transfers to and from ISO 20022 MX: MT940 / MT942 / MT950 ↔ camt.053 / camt.052, MT103 ↔ pacs.008, and MT202 / MT205 ↔ pacs.009. MX versions auto-detected on input.

Normalize to JSON

Parse either format into one frozen, stable canonical JSON shape built for bookkeeping and reconciliation — amounts always as strings, never floats.

Validation

Syntax and schema validation at selectable strictness levels, including CBPR+ checks. Always returns 200 with valid + findings[]; MX output validates against vendored ISO 20022 XSDs.

Enrichment

IBAN / BIC / code checks against free registry data, with a bring-your-own BIC directory plug point. Licensed directory data is never bundled.

Batch + webhooks

Async batch conversion with job polling and signed job.completed webhooks (retry ladder, X-Transmute-Signature).

Connectors

File-drop / SFTP connectors move files between customer-owned directories (in/ → out/) — nothing enters our custody.

On-prem / self-hosted

License-mode deployment for Enterprise: unlimited within license, rate limiting preserved, your infrastructure.

Structured warnings

Lossy or assumed conversion steps surface as deterministic, severity-graded warnings in the response — nothing is dropped silently.

Supported conversions

Directed pairs in the engine

MT940customer statement
camt.053camt.052
MT942interim report
camt.052camt.053
MT950statement
camt.053camt.052
camt.053bank-to-customer statement
MT940MT950
camt.052bank-to-customer report
MT940MT950
MT103single customer credit transfer
pacs.008
pacs.008FI-to-FI customer credit transfer
MT103
MT202 / MT205financial-institution transfer
pacs.009
pacs.009FI credit transfer
MT202MT205

Every parseable format additionally normalizes to canonical JSON.GET /v1/formats returns this registry live from the engine.

One call

Convert MT940 to camt.053

Authenticate with a bearer key, POST the message, get back the converted document plus severity-graded warnings and metadata. Raw MT text and bare XML work too.

curl -sS -X POST https://transmute-api.403fin.io/v1/convert \
  -H "Authorization: Bearer $TRANSMUTE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"from":"mt940","to":"camt.053","message":"..."}'
const res = await fetch("https://transmute-api.403fin.io/v1/convert", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TRANSMUTE_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ from: "mt940", to: "camt.053", message }),
});
const { result, warnings, meta } = await res.json();
import os, requests

res = requests.post(
    "https://transmute-api.403fin.io/v1/convert",
    headers={"Authorization": f"Bearer {os.environ['TRANSMUTE_KEY']}"},
    json={"from": "mt940", "to": "camt.053", "message": message},
)
data = res.json()  # {"result": "...camt.053...", "warnings": [...], "meta": {...}}
req, _ := http.NewRequest("POST",
    "https://transmute-api.403fin.io/v1/convert",
    strings.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("TRANSMUTE_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)

Full request body omitted for brevity — see the message payload in the quickstart. Sample data is synthetic (published example IBAN, TEST BICs).

How it works

Three steps, zero retained payload

1

Send the message

POST raw MT text, bare ISO 20022 XML, or a JSON envelope with from/to. Authenticate with a bearer API key.

2

We convert in memory

The engine parses, maps via declarative SR-versioned tables, and renders the target — all in request-scoped memory. Nothing is stored.

3

Get result + warnings

Receive the converted document (or canonical JSON) plus deterministic, severity-graded warnings. One row of usage metadata is all that remains.

Start converting today

Free tier: 1,000 conversions / month, no card required.