Skip to content

Developers

ISO 20022 API and MCP server

Detect, parse, validate and convert camt, pain and MT940 files over HTTP, or give an AI agent the same tools over MCP. Free, no key, nothing stored.

Base URL https://iso20022-navigator.com · OpenAPI 3.1 at /openapi.json

On this page

Overview

The parsers and validators behind the viewers, over HTTP for scripts and over the Model Context Protocol for AI agents. One implementation serves both, so a REST call and an MCP tool call return the same JSON.

  • No key, no account. Send a request; that’s all.
  • Machine-readable: the OpenAPI 3.1 document describes every endpoint and schema, and llms.txt is a short guide for language models.
  • Amounts are exact decimal strings ("12500.00"), never floating-point numbers.
Endpoints and MCP tools
EndpointWhat it doesMCP tool
POST /api/v1/detectDetect a message typedetect_message_type
POST /api/v1/parseParse to JSONparse_iso20022, parse_mt940
POST /api/v1/validateValidate a filevalidate_payment_file
POST /api/v1/convert/mt940-to-camt053Convert MT940 to camt.053convert_mt940_to_camt053
GET /api/v1/explainExplain a codeexplain_code

Limits

Limits
LimitValueOver the limit
AuthenticationNone: no key, no account, no cookies.—
Rate60 requests a minute per client (an IPv4 address, or an IPv6 /64 network), shared by the REST API and the MCP server.429 with Retry-After: 60
Size256 KB of file content per request (128 KB for the MT940 conversion). A JSON or JSON-RPC envelope around it may be somewhat larger.413; an MCP tool call gets a result with isError
CORSOpen (Access-Control-Allow-Origin: *) on /api/v1/*, /mcp, /openapi.json and /llms.txt: a web page on any site can call them.—
StorageRequest bodies are processed in memory and never stored or logged.—

256 KB holds a few hundred camt entries or pain transactions, more when they carry little detail. The MT940 conversion reads up to 128 KB, because the camt.053 it writes is several times larger than its input. For a bigger file, send it in parts (one statement or payment block per request) or open it in a viewer: the viewers run in your browser and open files up to 25 MB.

Sending a file

  • Raw body: the file text as the request body, with any content type. Send UTF-8. A charset in the Content-Type is honoured: 415 for a charset the server doesn’t read, 400 for bytes that don’t fit it. Without one, the body is read as the viewers read a file: UTF-8, UTF-16 when it starts with a byte-order mark, else Latin-1 (Windows-1252). XML that is not UTF-8 then fails validation with an xml.encoding error, as a bank’s parser would refuse it; an MT940 in Latin-1 is normal and reads as is.
  • JSON body: {"content": "<file text>"} with Content-Type: application/json, in UTF-8. Validate also takes "today": "YYYY-MM-DD", the date used for checks such as a requested execution date in the past (default: the current UTC date).
  • A body that opens like a JSON object ({") is read as JSON even without a JSON content type. MT940 ({1:) and XML (<) never are.
  • With curl, use --data-binary, not -d: -d strips line breaks, which MT940 needs and line numbers in findings rely on.

REST endpoints

All under https://iso20022-navigator.com. The four file endpoints take a POST with the file; explain takes a GET with query parameters. Every response is JSON except the converted XML.

Detect a message type

POSThttps://iso20022-navigator.com/api/v1/detectMCP: detect_message_type

What a file is: message type, full identifier and version, name, whether this API parses and validates it (supported) and converts it (convertible), the browser viewer for it, and the business application header when there is one. Reads only the start of the content.

curl -s --data-binary @statement.xml https://iso20022-navigator.com/api/v1/detect
jq -Rs '{content: .}' statement.xml \
  | curl -s -H 'Content-Type: application/json' --data-binary @- https://iso20022-navigator.com/api/v1/detect
200 · application/json
{
  "detection": {
    "kind": "iso20022",
    "messageType": "camt.053",
    "identifier": "camt.053.001.08",
    "version": "08",
    "name": "Bank-to-customer statement",
    "rootElement": "BkToCstmrStmt",
    "namespace": "urn:iso:std:iso:20022:tech:xsd:camt.053.001.08",
    "basis": "namespace",
    "supported": true,
    "convertible": false,
    "appHeader": null,
    "notes": [],
    "viewerUrl": "https://iso20022-navigator.com/"
  }
}

Parse to JSON

POSThttps://iso20022-navigator.com/api/v1/parseMCP: parse_iso20022, parse_mt940

Normalized JSON of the message. camt.052, camt.053 and camt.054: per statement the account, balances and entries, with references, counterparties, remittance and bank transaction codes. pain.001 and pain.008: group header, payment blocks and transactions. pain.002: statuses and reasons at every level. MT940 and MT942: every field and :61: subfield. Every block carries its line number and path. A file that is not a supported message, or not well-formed XML, gets a 422 with the reason as issues.

curl -s --data-binary @statement.xml https://iso20022-navigator.com/api/v1/parse
jq -Rs '{content: .}' statement.xml \
  | curl -s -H 'Content-Type: application/json' --data-binary @- https://iso20022-navigator.com/api/v1/parse
200 · application/json (excerpt)
{
  "detection": {
    "messageType": "camt.053",
    "identifier": "camt.053.001.08"
  },
  "summary": {
    "messageType": "camt.053",
    "valid": true,
    "statements": 2,
    "entries": 9,
    "transactions": 9
  },
  "counts": {
    "error": 0,
    "warning": 0,
    "info": 0
  },
  "document": {
    "kind": "camt",
    "type": "camt.053",
    "identifier": "camt.053.001.08",
    "statements": [
      {
        "path": "/Document/BkToCstmrStmt/Stmt[1]",
        "account": {
          "iban": "GB29NWBK60161331926819",
          "currency": "GBP",
          "ownerName": "Northwind Traders Ltd",
          "servicerBic": "NWBKGB2L"
        },
        "balances": [
          {
            "code": "OPBD",
            "line": 41,
            "amount": "125430.50",
            "currency": "GBP",
            "creditDebit": "CRDT",
            "date": "2026-10-27"
          }
        ],
        "entries": [
          {
            "line": 107,
            "amount": "12500.00",
            "currency": "GBP",
            "creditDebit": "CRDT",
            "status": "BOOK",
            "bookingDate": "2026-10-28",
            "valueDate": "2026-10-28",
            "servicerRef": "NW261028000101",
            "bankTxCode": {
              "description": "Payments · Received Credit Transfers · Domestic Credit Transfer",
              "domain": "PMNT",
              "family": "RCDT",
              "subFamily": "DMCT"
            }
          }
        ]
      }
    ]
  }
}

Excerpt: the first statement with its first balance and first entry; other fields and the transaction details are left out.

Validate a file

POSThttps://iso20022-navigator.com/api/v1/validateMCP: validate_payment_file

Every finding, with a rule id, severity (error, warning or info), message, XPath-like path and line number, and the found and expected values when they help. valid is true when there are no errors. Rule ids are stable: the 72 of them are listed in the reference. At most 500 issues per rule and severity are listed; truncated says when more were counted. A file that cannot be read is still a 200, with valid false and the reason as an issue, so a pipeline needs one code path.

curl -s --data-binary @statement.xml https://iso20022-navigator.com/api/v1/validate

With a fixed “today” for the date checks.

jq -Rs '{content: ., today: "2026-10-29"}' statement.xml \
  | curl -s -H 'Content-Type: application/json' --data-binary @- https://iso20022-navigator.com/api/v1/validate

Rule, line and message of each error, with jq.

curl -s --data-binary @statement.xml https://iso20022-navigator.com/api/v1/validate \
  | jq '.issues[] | select(.severity == "error") | {rule, line, message}'
200 · application/json (excerpt)
{
  "detection": {
    "messageType": "camt.053",
    "identifier": "camt.053.001.08"
  },
  "valid": false,
  "summary": {
    "messageType": "camt.053",
    "valid": false,
    "statements": 1,
    "entries": 3,
    "transactions": 1
  },
  "counts": {
    "error": 5,
    "warning": 6,
    "info": 0
  },
  "truncated": false,
  "issues": [
    {
      "rule": "iban.invalid",
      "severity": "error",
      "message": "Statement: account IBAN: DE89 3704 0044 0532 0130 01 is not a valid IBAN. The check digits 89 are wrong: the mod-97 test leaves 28 instead of 1, so a character is mistyped or two are swapped.",
      "path": "/Document/BkToCstmrStmt/Stmt/Acct/Id/IBAN",
      "line": 21,
      "found": "DE89370400440532013001",
      "hint": "Retype the IBAN from the source; a single wrong or swapped character fails the mod-97 check.",
      "title": "Invalid IBAN"
    },
    {
      "rule": "camt.balance.roll-forward",
      "severity": "error",
      "message": "Statement: OPBD 10000.00 EUR plus 3 booked entries (net 1249.50 EUR) gives 11249.50 EUR, but CLBD is 11650.00 EUR (difference 400.50).",
      "path": "/Document/BkToCstmrStmt/Stmt/Bal[2]",
      "line": 45,
      "found": "11650.00",
      "expected": "11249.50",
      "hint": "An entry is missing, duplicated or has the wrong credit/debit indicator — or this is one page of a statement that continues.",
      "title": "Balances do not roll forward"
    }
  ]
}

Excerpt for a statement with deliberate mistakes: 2 of its 11 issues, detection shortened.

Convert MT940 to camt.053

POSThttps://iso20022-navigator.com/api/v1/convert/mt940-to-camt053MCP: convert_mt940_to_camt053

Turns MT940 (or MT950) statements into one camt.053.001.08 document. The response is the XML itself, as an attachment, with X-Statements and X-Entries headers. With Accept: application/json it is a JSON object instead: the XML as a string, the message id, the counts, the mapping notes that apply to this file and the validation issues of the MT940 input. MT942, and input whose balances or entries cannot be read, get a 422: nothing is converted rather than data dropped. The field-by-field mapping and its limits are in the reference.

Saves the camt.053 next to the MT940.

curl -s --data-binary @statement.sta -o statement-camt053.xml https://iso20022-navigator.com/api/v1/convert/mt940-to-camt053

The XML inside JSON, with notes and input issues.

curl -s -H 'Accept: application/json' --data-binary @statement.sta https://iso20022-navigator.com/api/v1/convert/mt940-to-camt053
200 · response headers
HTTP/2 200
content-type: application/xml; charset=utf-8
content-disposition: attachment; filename="MT940-20261029080000-STMT301P1.xml"
x-statements: 3
x-entries: 7
200 · application/xml (start)
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08">
  <BkToCstmrStmt>
    <GrpHdr>
      <MsgId>MT940-20261029080000-STMT301P1</MsgId>
      <CreDtTm>2026-10-29T08:00:00+00:00</CreDtTm>
      <AddtlInf>Converted from SWIFT MT940 by ISO 20022 Navigator</AddtlInf>
    </GrpHdr>
    <Stmt>
      <Id>STMT301P1</Id>
      <StmtPgntn>
        <PgNb>1</PgNb>
        <LastPgInd>false</LastPgInd>
      </StmtPgntn>
      <ElctrncSeqNb>301</ElctrncSeqNb>
      …
200 · application/json (excerpt)
{
  "messageType": "camt.053.001.08",
  "messageId": "MT940-20261029080000-STMT301P1",
  "statements": 3,
  "entries": 7,
  "notes": [
    "Each :61: became one Ntry (status BOOK) with one TxDtls. :61: transaction types are kept as proprietary bank transaction codes (BkTxCd/Prtry, issuer SWIFT), not translated to ISO domain/family codes.",
    "MT940 has no creation time: GrpHdr/CreDtTm and Stmt/CreDtTm are the time of this conversion."
  ],
  "inputCounts": {
    "error": 0,
    "warning": 0,
    "info": 0
  },
  "inputIssues": []
}

Excerpt: the xml string (the whole document) and the remaining notes are left out.

Explain a code

GEThttps://iso20022-navigator.com/api/v1/explainMCP: explain_code

code (required, read up to 64 characters) is a balance type, a bank transaction code (one level, or PMNT/RCDT/ESCT), an entry or payment status, a reason code, an MT940 type code, a message type or a currency. kind narrows the search to one table: auto, balance_type, bank_transaction_code, entry_status, payment_status, status_reason, mt940_transaction_type, message_type, currency. With auto (the default) every table is searched, so PDNG returns both the entry status and the payment status. No match gives an empty matches list and a note.

curl -s 'https://iso20022-navigator.com/api/v1/explain?code=AC01'
curl -s 'https://iso20022-navigator.com/api/v1/explain?code=PDNG&kind=entry_status'
curl -s 'https://iso20022-navigator.com/api/v1/explain?code=PMNT/RCDT/ESCT'
200 · application/json
{
  "query": "AC01",
  "kind": "auto",
  "matches": [
    {
      "kind": "status_reason",
      "code": "AC01",
      "name": "Incorrect account number",
      "definition": "The account number is wrong (missing, invalid or does not exist).",
      "usedIn": "pain.002 / pacs.002 StsRsnInf/Rsn/Cd; returns RtrInf/Rsn/Cd"
    }
  ]
}

MCP server

The same operations as tools for AI agents, at https://iso20022-navigator.com/mcp.

  • Transport: Streamable HTTP, stateless. Each POST carries one JSON-RPC message and gets one JSON response: no session id, no server-sent events (GET and DELETE answer 405), no batches. tools/call works without a prior initialize.
  • Protocol versions: 2025-06-18, 2025-03-26, 2024-11-05. The server answers with the version the client asks for when it supports it, otherwise with 2025-06-18.
  • Methods: initialize, ping, tools/list and tools/call. Notifications get 202 with no body.
  • No key, and the REST limits apply: 60 requests a minute shared with the REST API, 256 KB of file content per call. Agents pass the file text itself in content, not a path or a URL.

Connect a client

Run in a terminal. Add --scope user to have it in every project.

claude mcp add --transport http iso20022-navigator https://iso20022-navigator.com/mcp

Settings → Connectors → Add custom connector, then paste this URL.

https://iso20022-navigator.com/mcp

Alternative for Claude Desktop, through mcp-remote (needs Node.js): add this to claude_desktop_config.json and restart the app.

{
  "mcpServers": {
    "iso20022-navigator": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://iso20022-navigator.com/mcp"
      ]
    }
  }
}

In .cursor/mcp.json (this project) or ~/.cursor/mcp.json (every project).

{
  "mcpServers": {
    "iso20022-navigator": {
      "url": "https://iso20022-navigator.com/mcp"
    }
  }
}

Other clients: one that speaks Streamable HTTP takes the URL directly; one that only starts local (stdio) servers can run npx -y mcp-remote https://iso20022-navigator.com/mcp. The server calls itself iso20022-navigator.

Raw JSON-RPC

What a client sends, with curl. The Accept header lists both types as the transport requires; responses are always JSON.

curl -s https://iso20022-navigator.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
curl -s https://iso20022-navigator.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s https://iso20022-navigator.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"explain_code","arguments":{"code":"OPBD"}}}'

jq puts the file text into the arguments.

jq -Rs '{jsonrpc: "2.0", id: 4, method: "tools/call", params: {name: "validate_payment_file", arguments: {content: .}}}' statement.xml \
  | curl -s https://iso20022-navigator.com/mcp \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json, text/event-stream' \
      --data-binary @-
initialize · 200 (excerpt)
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "iso20022-navigator",
      "title": "ISO 20022 Navigator",
      "version": "1.0.0"
    }
  }
}

The instructions text (a short guide to the tools for the model) is left out.

tools/call · 200
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"query\":\"OPBD\",\"kind\":\"auto\",\"matches\":[{\"kind\":\"balance_type\",\"code\":\"OPBD\",\"name\":\"Opening booked\",\"definition\":\"Book balance at the start of the reporting period: the closing booked balance of the previous statement.\",\"usedIn\":\"camt.052/053/054 Bal/Tp/CdOrPrtry/Cd\"}]}"
      }
    ],
    "structuredContent": {
      "query": "OPBD",
      "kind": "auto",
      "matches": [
        {
          "kind": "balance_type",
          "code": "OPBD",
          "name": "Opening booked",
          "definition": "Book balance at the start of the reporting period: the closing booked balance of the previous statement.",
          "usedIn": "camt.052/053/054 Bal/Tp/CdOrPrtry/Cd"
        }
      ]
    },
    "isError": false
  }
}

MCP tools

6 tools, as tools/list returns them. All are read-only and idempotent (readOnlyHint true, destructiveHint false): they read the text you pass and change nothing. Each returns its result as structuredContent and as JSON text in content.

detect_message_type

Detect message type. Identify a payment or bank-statement file. Recognizes ISO 20022 XML by its namespace (urn:iso:std:iso:20022:tech:xsd:camt.053.001.08) or, without one, by the element under <Document> — camt.052/053/054, pain.001/002/008, pacs.002/003/004/008/009, camt.029/055/056/060 and more — and SWIFT MT940/MT942/MT950 by their blocks and fields. Returns the message type, the full identifier with version, the message name, whether this server can parse, validate and convert it, the business application header (head.001) if present, and notes. Cheap: reads only the start of the content.

detect_message_type parameters
ParameterTypeRequiredDescription
contentstringYesThe complete file contents as text: ISO 20022 XML or SWIFT MT940/MT942. At most 256 KB. Pass the text itself, not a path or URL.

REST: POST /api/v1/detect

parse_iso20022

Parse ISO 20022 message. Parse an ISO 20022 XML message into normalized JSON. camt.052 (intraday account report), camt.053 (bank-to-customer statement) and camt.054 (debit/credit notification): per statement the account (IBAN or other id, currency, owner, servicer BIC), statement id, sequence numbers, period, balances (type code such as OPBD/CLBD/CLAV/ITBD, amount, credit/debit, date) and entries (amount, CRDT/DBIT, status BOOK/PDNG/INFO, reversal flag, booking and value dates, bank transaction code domain/family/sub-family with its meaning, AcctSvcrRef, batch info, and per transaction detail the EndToEndId/InstrId/MsgId/UETR, counterparty name/IBAN/BIC, remittance text and creditor reference, return reason). pain.001 (credit transfers) and pain.008 (direct debits): group header, payment information blocks and transactions. pain.002: original message, group/block/transaction statuses with reason codes. Amounts are exact decimal strings; every element carries its line number. Accepts versions .001.02 to .001.13 and any namespace prefix. Also accepts MT940/MT942 (same result as parse_mt940). Includes a summary and issue counts; call validate_payment_file for the list of issues.

parse_iso20022 parameters
ParameterTypeRequiredDescription
contentstringYesThe complete file contents as text: ISO 20022 XML or SWIFT MT940/MT942. At most 256 KB. Pass the text itself, not a path or URL.

REST: POST /api/v1/parse

validate_payment_file

Validate payment or statement file. Validate a camt.052/053/054, pain.001/002/008 or MT940/MT942 file and list every finding with a stable rule id, severity (error, warning or info), message, XPath-like path and line number, and the found/expected values when they help. Checks: XML well-formedness; required elements; balance roll-forward (opening booked balance + booked entries = closing booked balance; MT940 :60a: + :61: = :62a:); transaction summary (TxsSummry) and batch totals against the entries; NbOfTxs and CtrlSum at group-header and payment-information level; IBAN format, country length and mod-97 check digits; BIC format; ISO 4217 currency codes and decimals; Max35Text/Max140Text lengths; ISO dates; duplicate EndToEndId, PmtInfId, InstrId and AcctSvcrRef; requested execution or collection date in the past; SEPA rules when the service level is SEPA (EUR only, IBANs required, SEPA character set, 70-character names, one remittance line, SLEV, creditor id and mandate data for direct debits); pain.002 rejections without reasons and status consistency; MT940 field formats, lengths, character set, currencies and page chaining. "valid" is true when there are no errors; rules banks apply unevenly are warnings, not errors.

validate_payment_file parameters
ParameterTypeRequiredDescription
contentstringYesThe complete file contents as text: ISO 20022 XML or SWIFT MT940/MT942. At most 256 KB. Pass the text itself, not a path or URL.
todaystringNoOptional "today" (a real date written YYYY-MM-DD) for date checks such as a requested execution date in the past. Default: the current UTC date. Pattern ^\d{4}-\d{2}-\d{2}$.

REST: POST /api/v1/validate

parse_mt940

Parse SWIFT MT940/MT942. Parse SWIFT MT940 customer statements, MT942 interim reports or MT950 statements into JSON. Accepts complete FIN messages ({1:}{2:}{3:}{4: … -}{5:}) or bare field text starting with :20:, with one or many statements. Returns per statement: sender/receiver BIC from the headers, :20: reference, :25: account (IBAN when it is one), :28C: statement and sequence number, opening/closing/available/forward balances (D/C mark, date, currency, amount, signed amount), MT942 floor limits, date/time and :90D:/:90C: totals, and every :61: entry decoded: value date, entry date, D/C/RC/RD mark and its booking effect, funds code, amount, transaction type code with its meaning (NTRF = transfer, S103 = caused by an MT103), customer reference, bank reference, supplementary details, the :86: text and its structured subfields (?00–?63 German style or /CODE/ style: booking text, remittance, counterparty name, account and bank, EREF+/MREF+/CRED+ SEPA references). Amounts are decimal strings with a "." decimal point.

parse_mt940 parameters
ParameterTypeRequiredDescription
contentstringYesThe complete file contents as text: ISO 20022 XML or SWIFT MT940/MT942. At most 256 KB. Pass the text itself, not a path or URL.

REST: POST /api/v1/parse

convert_mt940_to_camt053

Convert MT940 to camt.053. Convert SWIFT MT940 (or MT950) statements to one ISO 20022 camt.053.001.08 XML document: one Stmt per MT940 statement, one Ntry with one TxDtls per :61:. Balances become OPBD/CLBD/CLAV/FWAV, :61: type codes are kept as proprietary bank transaction codes (BkTxCd/Prtry, issuer SWIFT) rather than guessed ISO domain codes, structured :86: subfields become counterparty, account, agent, EndToEndId, MndtId and remittance. Returns the XML string, its message id, statement and entry counts, notes describing the mapping and its limits for this file, and the validation issues of the MT940 input. Refuses input whose balances or entries cannot be read rather than dropping data; MT942 is refused (it maps to camt.052).

convert_mt940_to_camt053 parameters
ParameterTypeRequiredDescription
contentstringYesThe complete MT940 text (with or without SWIFT blocks). At most 128 KB.

REST: POST /api/v1/convert/mt940-to-camt053

explain_code

Explain a code. Explain an ISO 20022 or SWIFT code in plain words, with where it appears. Covers balance types (OPBD, CLBD, CLAV, OPAV, ITBD, ITAV, PRCD, FWAV, XPCD, INFO), bank transaction codes (a domain, family or sub-family such as PMNT, RCDT, ESCT, or a full "PMNT/RCDT/ESCT"), entry statuses (BOOK, PDNG, INFO, FUTR), payment statuses (RCVD, ACTC, ACCP, ACSP, ACSC, ACCC, PDNG, PART, RJCT, CANC…), status and return reason codes (AC01, AC04, AM04, MS03, MD07, RR04…), MT940 :61: transaction types (NTRF, NCHG, NDDT, S103 or the 3-letter TRF), message types (camt.053, pain.001.001.09) and ISO 4217 currency decimals (JPY, KWD). With kind "auto" every table is searched, so a code used in several (PDNG) returns each meaning.

explain_code parameters
ParameterTypeRequiredDescription
codestringYesThe code to explain, e.g. "OPBD", "PMNT/RCDT/ESCT", "AC01", "NTRF", "camt.053". At most 64 characters.
kindstringNoWhich table to search. Default "auto" (all of them). One of auto, balance_type, bank_transaction_code, entry_status, payment_status, status_reason, mt940_transaction_type, message_type, currency.

REST: GET /api/v1/explain

Errors

REST errors are JSON with an error sentence that says what to send instead. MCP separates protocol errors (a JSON-RPC error) from problems with the file (a normal result with isError).

HTTP status codes

HTTP status codes
StatusWhen
200Success. Validate answers 200 even for a file it cannot read: valid false, with the reason as an issue.
400Empty content; a JSON body without a content string, invalid JSON sent as JSON, or a JSON body that is not UTF-8; bytes that don’t fit the charset the Content-Type names; today not a real date written YYYY-MM-DD; explain without code or with an unknown kind.
405Wrong method (POST for the file endpoints and /mcp, GET for explain). The Allow header names the right one.
413More than 256 KB of file content (128 KB for the conversion).
415The Content-Type names a charset the server doesn’t read. Send UTF-8, or leave the charset out.
422Parse: not a supported message, or not well-formed XML. Convert: not an MT940, an MT942, or balances or entries that cannot be read. The body adds the detection and, where there are any, the issues.
429More than 60 requests a minute from this client. Wait for Retry-After (60 seconds).
400 · application/json
{
  "error": "The content is empty: send the file text as the request body, or JSON {\"content\": \"…\"}."
}

JSON-RPC errors

JSON-RPC error codes
CodeErrorWhenHTTP
-32700Parse errorThe body is not JSON, or not UTF-8.400
-32600Invalid requestNot a JSON-RPC 2.0 object, a batch (array), a missing or non-string method, a bad id, or an MCP-Protocol-Version header that is malformed or names a version other than 2025-06-18, 2025-03-26, 2024-11-05. Also a request far over the size limit.400 (413 for size)
-32601Method not foundAnything but initialize, ping, tools/list and tools/call.200
-32602Invalid paramsparams not an object; tools/call without a name or with an unknown tool; arguments that don’t fit the tool’s schema (no content or code string, today not a real date written YYYY-MM-DD, an unknown kind).200
-32603Internal errorThe server failed while handling the request. The response still carries its id.200
-32000Rate limitMore than 60 requests a minute from this client (id is null).429 with Retry-After: 60

Tool results with isError

A file the tool cannot work with is not a protocol error: tools/call returns a result with isError true and the reason in structuredContent (and as text), so the model can read it and try again. That covers an empty file, a file that is not a supported message, an MT942 or a camt file sent to convert_mt940_to_camt053, and content over 256 KB (128 KB for the conversion).

tools/call convert_mt940_to_camt053 with a camt.053 · 200 (excerpt)
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "structuredContent": {
      "error": "Only MT940 (or MT950) statements can be converted; this is camt.053.001.08."
    },
    "isError": true
  }
}

Excerpt: the content text and the detection are left out.

Privacy

  • Request bodies are read into memory, processed and dropped. They are never stored and never logged.
  • The only record kept is an anonymous count per operation (such as api:validate or mcp:validate_payment_file), published on the analytics page.
  • Cloudflare, which runs the site, handles the connection and your IP address; the rate limit is keyed on it (an IPv4 address or an IPv6 /64).
  • Rather not send a file anywhere? The camt Statement Viewer, Payment File Viewer and MT940 Viewer do the same work in your browser, with nothing uploaded.

The full policy is on the privacy page.