Anonymize
POST /v1/anonymize replaces names, accounts, BICs, references and free text with synthetic values and returns the message in its original format, so you can share it safely.
What it is for
When a conversion surprises you, the fastest fix starts with the message that caused it. But a real payment or statement holds personal and commercial data that you should not paste into a support ticket, a bug report or a test fixture.
POST /v1/anonymize gives you a copy of the message that keeps its structure and drops the data. It reads the message, replaces every identifying value with a synthetic one of the same shape, and writes it back out in the same format. An MT103 comes back as an MT103 and a camt.053 as a camt.053, with the same fields, codes, currencies, dates and amounts. The copy still reproduces most format and mapping problems, and it no longer identifies anyone.
Send a message
Request forms match Convert: a JSON envelope, raw MT as text/plain, or raw XML. There is no to; the output format is the input format. from is optional and detected when you leave it out.
curl -sS -X POST https://api.transmute.403fin.io/v1/anonymize \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: text/plain" \
-H "Accept: text/plain" \
--data-binary @statement.mt940
For the sample MT940 statement in the Quickstart, the output looks like this (your values will differ; see Salt below):
:20:HINA5891
:25:DE72… synthetic German IBAN, valid check digits
:28C:00042/001
:60F:C260601EUR1000,00
:61:2606020602C250,00NTRFNONREF//QADTZOW9
:86:REDACTED
:62F:C260602EUR1250,00
The statement reference, the account and the bank reference are replaced; the remittance text is redacted; the statement number, balances, dates, the entry amount and the transaction code are unchanged.
With the default Accept: application/json you get an envelope instead:
{
"result": ":20:EYMO4023\r
:25:DE84…\r
:28C:00042/001\r
...",
"warnings": [],
"meta": {
"detectedType": "mt940",
"detectedVersion": null,
"targetType": "mt940",
"durationMs": 2,
"salt": "random"
}
}
result is an array of strings when the MT output spans several pages, as with Convert. Accept: application/xml returns the bare document for an ISO 20022 message, and Accept: text/plain for an MT message; asking for the other one is an invalid-input 400.
What is replaced, and how
| Content | Becomes |
|---|---|
| Party and agent names | NAME-1, NAME-2, and so on. The same name always gets the same number within one message |
| IBANs | A synthetic IBAN of the same country and the same shape (digits stay digits, letters stay letters) with valid check digits, so it still passes IBAN validation |
| BICs | A BIC from the test range (AAAA…, BBBB…) with the same country code and the same length. The 8- and 11-character forms of one bank map to the same replacement |
| References, ids and account numbers | A keyed hash of the same length and character classes (digits stay digits, letters stay letters, punctuation stays). An RF creditor reference gets new valid check digits; placeholders such as NONREF and NOTPROVIDED are kept |
| UETRs | A UUID derived from the original, still in the standard format |
Free text: remittance information, MT :86:, narratives, address lines | REDACTED, repeated and cut to the largest power of two not above the original length. A leading MT code word such as /INV/ is kept |
| Codes, currencies, countries, dates and amounts | Unchanged |
Because every replacement keeps the original's length and character set, the result still fits the target format's field widths and character rules.
Text length is only revealed to the nearest power of two: an original of 12 characters and one of 15 both become 8.
The output carries no transport headers. MT block 1 to 3 headers and the ISO 20022 business application header name the sending and receiving banks, so they are dropped rather than anonymized.
Bucket amounts
Amounts are kept by default, since many problems depend on them. To hide them too, send "options": { "amounts": "bucket" } (or ?amounts=bucket with a raw body). Each transaction amount is then rounded to the nearest power of ten, and never below the currency's smallest unit: 250,00 becomes 100,.
Balances and statement totals are never changed. A bucketed statement's balances therefore no longer add up to its entries.
Salt: repeatable output
Replacement values are derived from the original with a secret key, the salt.
- Default: a fresh random salt for every request. Anonymizing the same message twice gives two different results that cannot be linked to each other.
meta.saltisrandom. - Your own salt. Send
options.saltin the JSON envelope or theX-Transmute-Anonymize-Saltheader, 16 to 256 characters. The same input and salt then always give the same output, so you can anonymize a set of related messages consistently: a reference that appears in a payment and in the statement that books it maps to the same value in both.meta.saltiscaller.
A fixed salt makes outputs linkable across calls. Anyone who knows the salt can also test guesses of short references against the output. Treat the salt like a password. transmute never echoes or logs it, and refuses it in the query string, where proxies would log it: ?salt= is an invalid-input 400.
Formats that cannot be anonymized
Anonymize needs to write the message back in its own format. These return unsupported-conversion 422:
- formats transmute reads but does not write: the normalize-only
camt.029,mt199andmt299, and the source-onlycamt.055 - the file formats transmute only writes, such as
csv-xeroandofx - an individual message whose content cannot be written back into its own format
GET /v1/formats shows which formats can be read and written.
Before you share the output
Anonymize replaces every value in the fields listed above. It cannot know what you wrote into a field meant for something else, for example a name typed into a reference field. Read the output before you send it anywhere, and use amounts: "bucket" when the amounts themselves are sensitive.
Privacy
Your original message is processed in memory and is not stored or logged. The anonymized copy is returned in the HTTP response. If you send an Idempotency-Key, that response is also kept in the replay cache for 24 hours. The usage record for the call holds the format id and a warning count, never content and never the salt.
Access and billing
Requires the convert scope. Each call counts as one conversion under the usual billing rules.