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.office-odds.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.
| Endpoint | What it does | MCP tool |
|---|---|---|
| POST /api/v1/detect | Detect a message type | detect_message_type |
| POST /api/v1/parse | Parse to JSON | parse_iso20022, parse_mt940 |
| POST /api/v1/validate | Validate a file | validate_payment_file |
| POST /api/v1/convert/mt940-to-camt053 | Convert MT940 to camt.053 | convert_mt940_to_camt053 |
| GET /api/v1/explain | Explain a code | explain_code |
Limits
| Limit | Value | Over the limit |
|---|---|---|
| Authentication | None: no key, no account, no cookies. | — |
| Rate | 60 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 |
| Size | 256 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 |
| CORS | Open (Access-Control-Allow-Origin: *) on /api/v1/*, /mcp, /openapi.json and /llms.txt: a web page on any site can call them. | — |
| Storage | Request 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
charsetin theContent-Typeis honoured:415for a charset the server doesn’t read,400for 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 anxml.encodingerror, as a bank’s parser would refuse it; an MT940 in Latin-1 is normal and reads as is. - JSON body:
{"content": "<file text>"}withContent-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:-dstrips line breaks, which MT940 needs and line numbers in findings rely on.
REST endpoints
All under https://iso20022.office-odds.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.office-odds.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.office-odds.com/api/v1/detectjq -Rs '{content: .}' statement.xml \
| curl -s -H 'Content-Type: application/json' --data-binary @- https://iso20022.office-odds.com/api/v1/detect{
"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.office-odds.com/"
}
}Parse to JSON
POSThttps://iso20022.office-odds.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.office-odds.com/api/v1/parsejq -Rs '{content: .}' statement.xml \
| curl -s -H 'Content-Type: application/json' --data-binary @- https://iso20022.office-odds.com/api/v1/parse{
"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.office-odds.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.office-odds.com/api/v1/validateWith 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.office-odds.com/api/v1/validateRule, line and message of each error, with jq.
curl -s --data-binary @statement.xml https://iso20022.office-odds.com/api/v1/validate \
| jq '.issues[] | select(.severity == "error") | {rule, line, message}'{
"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.office-odds.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.office-odds.com/api/v1/convert/mt940-to-camt053The XML inside JSON, with notes and input issues.
curl -s -H 'Accept: application/json' --data-binary @statement.sta https://iso20022.office-odds.com/api/v1/convert/mt940-to-camt053HTTP/2 200
content-type: application/xml; charset=utf-8
content-disposition: attachment; filename="MT940-20261029080000-STMT301P1.xml"
x-statements: 3
x-entries: 7<?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>
…{
"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.office-odds.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.office-odds.com/api/v1/explain?code=AC01'curl -s 'https://iso20022.office-odds.com/api/v1/explain?code=PDNG&kind=entry_status'curl -s 'https://iso20022.office-odds.com/api/v1/explain?code=PMNT/RCDT/ESCT'{
"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.office-odds.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/callworks without a priorinitialize. - 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 with2025-06-18. - Methods:
initialize,ping,tools/listandtools/call. Notifications get202with 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.office-odds.com/mcpSettings → Connectors → Add custom connector, then paste this URL.
https://iso20022.office-odds.com/mcpAlternative 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.office-odds.com/mcp"
]
}
}
}In .cursor/mcp.json (this project) or ~/.cursor/mcp.json (every project).
{
"mcpServers": {
"iso20022-navigator": {
"url": "https://iso20022.office-odds.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.office-odds.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.office-odds.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.office-odds.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.office-odds.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.office-odds.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data-binary @-{
"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.
{
"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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The 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. |
| today | string | No | Optional "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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The 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).
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The complete MT940 text (with or without SWIFT blocks). At most 128 KB. |
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| code | string | Yes | The code to explain, e.g. "OPBD", "PMNT/RCDT/ESCT", "AC01", "NTRF", "camt.053". At most 64 characters. |
| kind | string | No | Which 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
| Status | When |
|---|---|
| 200 | Success. Validate answers 200 even for a file it cannot read: valid false, with the reason as an issue. |
| 400 | Empty 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. |
| 405 | Wrong method (POST for the file endpoints and /mcp, GET for explain). The Allow header names the right one. |
| 413 | More than 256 KB of file content (128 KB for the conversion). |
| 415 | The Content-Type names a charset the server doesn’t read. Send UTF-8, or leave the charset out. |
| 422 | Parse: 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. |
| 429 | More than 60 requests a minute from this client. Wait for Retry-After (60 seconds). |
{
"error": "The content is empty: send the file text as the request body, or JSON {\"content\": \"…\"}."
}JSON-RPC errors
| Code | Error | When | HTTP |
|---|---|---|---|
| -32700 | Parse error | The body is not JSON, or not UTF-8. | 400 |
| -32600 | Invalid request | Not 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) |
| -32601 | Method not found | Anything but initialize, ping, tools/list and tools/call. | 200 |
| -32602 | Invalid params | params 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 |
| -32603 | Internal error | The server failed while handling the request. The response still carries its id. | 200 |
| -32000 | Rate limit | More 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).
{
"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:validateormcp: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.