Round-trip verification
Check a conversion for silent data loss. Verify re-reads the converted output and reports every value that did not survive, split into warned and silent losses.
What verify answers
Some conversions cannot carry everything. A camt.053 statement can name the counterparty's bank; MT940 has no field for it. transmute reports each such loss as a warning. Verify checks that promise for one specific message: was anything lost without a warning?
It converts your message exactly as Convert does, reads the output back, and compares the result with your source. The comparison walks a checklist of value-bearing fields for the message family (payments, statements, initiations, and so on): amounts, dates, BICs, IBANs, references, UETRs, names, addresses and free text. Each value either comes back, or it is reported as lost.
Two ways to call it
| Route | Returns | Use when |
|---|---|---|
POST /v1/verify | The loss report, the conversion's warnings and meta, but not the converted document | You want to check a message, not use the output |
POST /v1/convert with verify | The normal convert response plus the same loss report | You want the converted document and the check in one call |
To add the report to a conversion, send "options": { "verify": true } in the JSON envelope, or ?verify=true (or the X-Transmute-Verify: true header; the query parameter wins) with a raw body. The conversion runs once; verify only reads its output back.
POST /v1/verify takes the same request forms, query parameters, headers and options as POST /v1/convert (a JSON envelope, raw MT as text/plain, or raw XML), with to required:
curl -sS -X POST "https://api.transmute.403fin.io/v1/verify?to=camt.053" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
--data-binary @statement.mt940
{
"verify": {
"family": "statement",
"survived": 14,
"lost": [],
"warned": [],
"silent": []
},
"warnings": [ { "code": "MISSING_REQUIRED_DEFAULTED", "...": "..." } ],
"meta": { "detectedType": "mt940", "targetType": "camt.053.001.08", "durationMs": 4 }
}
The report is JSON only. With verify on /v1/convert, a bare-document or zip Accept is an invalid-input 400. Batch items reject verify.
Read the report
| Field | Meaning |
|---|---|
family | The message family whose checklist was used, such as payment or statement |
survived | How many value-bearing source values were found again in the output |
lost | Every value that was not found again. Always warned plus silent |
warned | Lost values that a loss warning names. These are expected and documented |
silent | Lost values that no warning names. This list should always be empty |
Each entry in lost, warned and silent looks like this:
{ "invariant": "counterparty-bics", "class": "bic", "value": "AAAADEFFXXX", "codes": ["DROP_FIELD"] }
| Field | Meaning |
|---|---|
invariant | The checklist row, such as settled-amount, agent-bics or counterparty-bics |
class | The kind of value: amount, date, bic, iban, ref, uetr, text or address |
value | The source value that did not come back |
codes | The loss warnings that name this field. Absent on a silent entry |
A value counts as warned when the conversion raised a loss warning for its field: a TRUNC_*, DROP_* or CHARSET_* code, OVERRIDE_SUPPRESSED or FIELD_OVERSIZED. Any other lost value is silent.
Two rules keep the report free of noise:
- Re-wrapped text survives. MT fields have short lines, so long text is split differently on the way. Text that only changed by line breaks counts as found.
- Transliterated text is a warned loss. When text had to be rewritten into the SWIFT character set (for example
ÄtoAE) for an MT target, it counts as lost under the matchingCHARSET_*warning.
What to do with the result
silentis empty andwarnedis empty: every checked value made it across.warnedhas entries: the target format cannot hold these values. The warnings tell you which fields and why. Decide whether that is acceptable for your flow, or send the values another way. A camt.053 converted to MT940, for example, loses counterparty BICs, names and addresses underDROP_FIELD.silenthas entries: transmute lost a value without telling you. That is a defect. Contact support with the request id from theX-Request-Idheader and, if you can, an anonymized copy of the message.
Limits
- Targets that transmute writes but cannot read back cannot be verified:
csv-xero,ofx,qfxandqboreturnunsupported-conversion422. - Everything that would make the conversion fail (an unknown format, an unsupported pair, a body over the size cap) fails verify the same way.
Privacy
Report entries quote the source value, so you can find the field in your message. Like the converted document, the report exists only in the HTTP response. transmute does not store or log it.
Access and billing
Both forms need the convert scope. POST /v1/verify counts as one conversion, and verify on a convert request is part of that conversion, with no separate charge. The usual billing rules apply.