Trust & ToolingAnonymize

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

ContentBecomes
Party and agent namesNAME-1, NAME-2, and so on. The same name always gets the same number within one message
IBANsA 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
BICsA 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 numbersA 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
UETRsA UUID derived from the original, still in the standard format
Free text: remittance information, MT :86:, narratives, address linesREDACTED, 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 amountsUnchanged

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.salt is random.
  • Your own salt. Send options.salt in the JSON envelope or the X-Transmute-Anonymize-Salt header, 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.salt is caller.

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, mt199 and mt299, and the source-only camt.055
  • the file formats transmute only writes, such as csv-xero and ofx
  • 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.