Quickstart
Convert a SWIFT MT940 statement to ISO 20022 camt.053, normalize it to canonical JSON, and validate it — three curls with a test key.
Before you start
You need an API key — a tk_test_ key is perfect here (get one): it never bills, and this whole quickstart uses a handful of your account's one-time 250-request test allowance. Every block below is copy-paste runnable; the sample message is synthetic (TEST BICs, a published example IBAN).
export TRANSMUTE_KEY=tk_test_... # your key
export BASE=https://api.transmute.403fin.io
1. Check the service
curl -fsS $BASE/v1/health # {"status":"ok"} — no auth needed
2. Convert an MT940 to camt.053
POST the bare MT text (text/plain) with the target in the query string — no JSON escaping needed:
curl -sS -X POST "$BASE/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
:62F:C260602EUR1250,00
-}
EOF
# {"result":"<?xml ... camt.053.001.08 ...","warnings":[...],"meta":{...}}
The from format was auto-detected (meta.detectedType: "mt940"). You can also send a JSON envelope ({"from","to","message","options"}) or raw ISO 20022 XML — see Convert.
3. Read the warnings array
Nothing is dropped silently. MT940 carries no creation timestamp, so the converter tells you it defaulted the mandatory camt.053 CreDtTm:
"warnings": [
{ "code": "MISSING_REQUIRED_DEFAULTED", "severity": "info",
"sourceField": "statement[0].createdAt", "targetField": "GrpHdr/CreDtTm",
"detail": "no createdAt in canonical source; defaulted to conversion time (UTC)" }
]
Each warning has a stable code from the warning registry, a severity (info < warning < lossy < error), optional sourceField/targetField paths, and a short detail — never message content. Treat lossy entries as review items in reconciliation pipelines.
4. Normalize to canonical JSON
Same raw form. Amounts come back as strings — never floats:
curl -sS -X POST "$BASE/v1/normalize?from=mt940" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
--data-binary @statement.mt940
# {"result":{"type":"statement","statement":{...}},"warnings":[...]}
5. Validate
Validation problems in the message come back as findings in a 200, not as errors:
curl -sS -X POST "$BASE/v1/validate?from=mt940&level=schema" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
--data-binary @statement.mt940
# {"valid":true,"findings":[]}
6. Watch your quota tick
Every metered response carries body-free observability headers:
X-Request-Id: req_01J... # quote this to support
X-Quota-Limit: 250 # the pool this key draws from — the one-time
# test allowance here; your monthly quota on
# a live key (Free: 1000)
X-Quota-Remaining: 246 # before this request
RateLimit-Remaining: 99 # token bucket, per second
See Response Headers and Rate Limits & Quotas.
Next steps
- Convert — content types, options, paging, XML in/out
- Supported formats —
GET /v1/formatsis the live registry - SDKs — Go, TypeScript, Python clients
- Interactive endpoint reference: api.transmute.403fin.io/docs