Versions & EnvelopesMessage Envelopes

Message Envelopes

Carry routing headers across a conversion: FIN blocks 1-3 on MT messages and the ISO 20022 Business Application Header (AppHdr) on MX messages, with the envelope option on convert and normalize.

What an envelope is

A financial message travels inside a transport wrapper that says who sent it, who receives it and what it is. transmute calls that wrapper the envelope, and handles two kinds:

KindFormatCarries
FIN header blocksMT. The {1:}, {2:} and {3:} blocks in front of the {4:} text block.Sender and receiver addresses (BIC-based), message type, priority, and in block 3 the Message User Reference ({108:}) and the UETR ({121:})
Business Application Header (AppHdr)MX. An ISO 20022 head.001 document that travels next to the business Document.Sender (Fr) and receiver (To) BICs, business message id (BizMsgIdr), message definition (MsgDefIdr), creation time (CreDt), priority (Prty)

A BIC is the 8- or 11-character bank identifier code (AAAADEFF). A UETR is the end-to-end tracking reference of a payment.

Envelope handling is opt-in. By default (envelope=none) transmute converts the business message only, and its output and warnings do not depend on envelope data at all.

Envelopes on input

Envelopes never get in the way of parsing. An MT message may arrive with or without blocks 1 to 3. An MX message is accepted in any of these shapes:

  1. a bare Document;
  2. an AppHdr and a Document side by side, either inside a wrapper element or as two top-level elements one after the other (as some gateways send them);
  3. a wrapping envelope such as BizMsgEnvlp, with the AppHdr and Document nested inside.

transmute finds the first Document in an ISO 20022 namespace; everything around it is envelope. The AppHdr is read in every head.001 version, and fields it does not model are ignored.

/v1/validate at level=schema also checks a head.001.001.02 AppHdr that travels with the Document: the required Fr, To, BizMsgIdr, MsgDefIdr and CreDt, and the BIC and date-time shapes. Its findings are prefixed AppHdr.. See Validate.

The envelope option

EndpointValuesEffect
/v1/convertnone (default)Business message only
apphdrMX targets. Emit a head.001.001.02 AppHdr built from the source's envelope, then the Document
finMT targets. Wrap every output message in FIN blocks 1 and 2 built from the source's envelope
/v1/normalizenone (default), includeinclude adds the source envelope to the normalized JSON as result.envelope

Send it as options.envelope in a JSON envelope, as ?envelope= on raw bodies, or as the X-Transmute-Envelope header (in that order of precedence).

These are invalid-input 400s, because routing data is never invented:

  • a value that does not fit the target, for example envelope=apphdr with to=mt103 or envelope=fin with an MX target;
  • a source that does not carry both a sender and a receiver BIC (no FIN blocks 1 and 2 on an MT source, no AppHdr on an MX source).
{
  "type": "https://docs.transmute.403fin.io/errors/invalid-input",
  "title": "Invalid input",
  "status": 400,
  "detail": "Envelope option cannot be applied: envelope=fin needs the source to carry sender and receiver BICs (FIN blocks 1 and 2 for MT, an AppHdr for MX)",
  "instance": "/v1/convert"
}

MT in, AppHdr out (envelope=apphdr)

curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?to=pacs.008&envelope=apphdr" \
  -H "Authorization: Bearer $TRANSMUTE_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary @- <<'MSG'
{1:F01AAAADEFFAXXX0000000000}{2:I103BBBBDEFFXXXXN}{3:{108:MUR-DOCS-01}{121:00000000-0000-4000-8000-000000000103}}{4:
:20:ENVDOCS001
:23B:CRED
:32A:261002EUR250,00
:50K:/DE89370400440532013000
MAX EXAMPLE
:59:/GB29NWBK60161331926819
ERIKA EXAMPLE
:71A:SHA
-}
MSG

result holds two top-level elements, the AppHdr and then the Document. transmute never wraps them in a BizMsgEnvlp. Shortened:

<?xml version="1.0" encoding="UTF-8"?>
<AppHdr xmlns="urn:iso:std:iso:20022:tech:xsd:head.001.001.02"><Fr><FIId><FinInstnId><BICFI>AAAADEFF</BICFI></FinInstnId></FIId></Fr><To><FIId><FinInstnId><BICFI>BBBBDEFF</BICFI></FinInstnId></FIId></To><BizMsgIdr>ENVDOCS001</BizMsgIdr><MsgDefIdr>pacs.008.001.08</MsgDefIdr><CreDt>2026-10-08T10:56:57Z</CreDt><Prty>NORM</Prty></AppHdr><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.08">...</Document>

How the AppHdr is filled:

AppHdr elementComes from
Fr / ToSender and receiver BICs from blocks 1 and 2
BizMsgIdrThe MT :20: reference. Absent: NOTPROVIDED with MISSING_REQUIRED_DEFAULTED. Longer than 35 characters: TRUNC_REFERENCE.
MsgDefIdrAlways the Document actually rendered (pacs.008.001.08 here)
CreDtThe source envelope's creation time. An MT header has none, so it is the request time with MISSING_REQUIRED_DEFAULTED (info).
PrtyBlock 2 priority: N becomes NORM, U becomes HIGH

The {108:} Message User Reference has no AppHdr slot, so it is reported as ENVELOPE_DROPPED (info). The UETR still reaches the Document through the payment mapping, as it does without an envelope.

AppHdr in, MT out (envelope=fin)

Send the AppHdr and Document produced above to to=mt103&envelope=fin and the MT output gets FIN blocks 1 and 2:

{1:F01AAAADEFFAXXX0000000000}{2:I103BBBBDEFFAXXXN}{3:{121:00000000-0000-4000-8000-000000000103}}{4:
:20:ENVDOCS001
...
-}
FIN elementComes from
Block 1 addressThe AppHdr sender BIC, as a 12-character terminal address
Block 2 destinationThe AppHdr receiver BIC
Block 2 message typeThe MT target
Block 2 priorityNORM becomes N; HIGH and URGT become U; anything else is N with ENVELOPE_DROPPED
Block 1 session and sequence numbersZero placeholders (0000, 000000) with MISSING_REQUIRED_DEFAULTED. Your interface assigns the real numbers when it sends the message.
Block 3Kept when the MT renderer writes one (the {121:} UETR of an MT103)

The AppHdr BizMsgIdr and CreDt have no slot in an input FIN header, so each is reported as ENVELOPE_DROPPED (info). The :20: reference in the text block still carries the transaction reference. When MT paging splits the output, every page gets the envelope.

Normalize with the envelope (envelope=include)

curl -sS -X POST "https://api.transmute.403fin.io/v1/normalize?envelope=include" \
  -H "Authorization: Bearer $TRANSMUTE_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary @mt103.txt

The envelope arrives as result.envelope, beside the business document and never inside it:

{
  "result": {
    "type": "payment",
    "payment": { "...": "..." },
    "envelope": {
      "senderBic": "AAAADEFF",
      "receiverBic": "BBBBDEFF",
      "messageId": "ENVDOCS001",
      "messageDefinition": "MT103",
      "priority": "NORM",
      "mur": "MUR-DOCS-01",
      "uetr": "00000000-0000-4000-8000-000000000103"
    }
  },
  "warnings": [],
  "meta": { "...": "..." }
}
MemberMT sourceMX source
senderBic / receiverBicBlocks 1 and 2AppHdr Fr / To
messageId:20:BizMsgIdr
messageDefinitionMT + message typeMsgDefIdr
createdAt(none)CreDt, as a date-time with an explicit offset
priorityNORM, HIGH, or the block 2 code as sentPrty
murBlock 3 {108:}(none)
uetrBlock 3 {121:}(none)

Every member is optional and omitted when empty. A source without an envelope gives no result.envelope.

If you send the normalized JSON back with from=canonical, result.envelope feeds envelope=apphdr and envelope=fin exactly like a native envelope. See Normalize.

Envelope warnings

CodeSeverityRaised when
ENVELOPE_MISMATCHwarningAn incoming AppHdr's MsgDefIdr names a different message than the namespace of the Document it travels with. Read only when an envelope option is set.
ENVELOPE_DROPPEDinfoAn envelope component (the MUR, BizMsgIdr, CreDt, a priority with no counterpart, an AppHdr BizSvc) has no slot in the envelope you asked for, or an incoming AppHdr value is not in a usable form
{ "code": "ENVELOPE_MISMATCH", "severity": "warning",
  "sourceField": "AppHdr/MsgDefIdr", "targetField": "messageDefinition",
  "detail": "AppHdr message definition (length 15) does not match the Document namespace" }

Envelope warnings, like all warnings, name fields and lengths only, never values. The full list is in the warning registry.