ISO 20022 is the standard that defines many XML messages for FinTech. It is very general, and often countries/orgs define subsets (TVS, technical validation subset) of the schema.
Documentation for message fields can be viewed at https://www.iso20022.org/standardsrepository.
The primary syntax for ISO 20022 messages is XML. To avoid LibEuFin clients having to deal with XML, we define a mapping from ISO 20022 messages into JSON.
The specifics of this mapping are:
- The JSON should be “idiomatic” and easy to process.
- When possible, the highly nested structures of ISO 20022 should be flattened.
- It must be possible round-trip between the LibEuFin JSON and ISO 20022 XML messages. The mapping of message types is not 1-to-1, as some ISO 20022 messages are very similar and can be mapped to the same JSON structure.
- JSON-mapped messages are not explicitly versioned. Instead, changes are made in a backwards-compatible way, possibly preserving old versions of message elements in the same schema.
While LibEuFin can communicate ISO 20022 messages (camt.05x, pain.001) to other parties, it does not model its own authored API and internal data after the ISO 20022 standard.
Objections to ISO20022:
Instead of using ISO 20022 messages directly, LibEuFin leverages the standard in other ways:
- ISO 20022: Mandatory, with debit/credit indicator. Indicates money moving in/out of the account in the account’s currency.
- LibEuFin: Same.
- ISO 20022: Optional, direction-less. Amount of money moving between the debtor and creditor bank, may not be in the account’s currency (but the “native” currency between the two banks).
- LibEuFin: Same.
- ISO 20022: Optional, direction-less. Amount of money specified in the payment initiation message. Usually only specified when the amount is in a different currency than the account currency.
- LibEuFin: Same.
FIXME: This is not complete yet.
interface NexusTransactionsReponse {
entries: NexusAccountEntryItem[];
}
interface NexusAccountEntryItem {
nexusEntryId: string;
// Serial number that will increase with each update
// to the entry.
nexusStatusSequenceId: number;
entry: AccountEntryItem;
}
interface AccountEntryItem {
// At least one of entryId or accountServicerRef
// must be non-null
entryId?: string;
accountServicerRef?: string;
creditDebitIndicator: "credit" | "debit";
amount: string;
currency: string;
instructedAmountDetails?: {
amount: string;
currency: string;
currencyExchange?: {
sourceCurrency: string;
targetCurrency: string;
unitCurrency: string;
exchangeRate: string;
contractId: string;
quotationDate: string;
};
};
status: "booked" | "pending" | "info";
valueDate?: string;
bookingDate?: string;
mandateId?: string;
endToEndId?: string;
messageId?: string;
creditor?: Party
creditorAgent?: FinancialInstitution;
creditorAccount?: FinancialInstitution;
debtor?: Party
debtorAgent?: FinancialInstitution;
debtorAccount?: FinancialInstitution;
unstructuredRemittanceInformation?: string;
bankTransactionCode: BankTransactionCode;
}
interface Party {
name?: string;
partyType: "private" | "organization";
otherId?: {
id: string;
schemeName?: string;
issuer?: string;
};
}
interface Account {
name?: string;
currency?: string;
otherId?: {
id: string;
schemeName?: string;
issuer?: string;
};
}
interface FinancialInstitution {
type: "financial-institution";
name?: string;
bic?: string;
otherId?: {
id: string;
schemeName?: string;
issuer?: string;
};
}
interface BankTransactionCode {
domain?: string;
family?: string;
subfamily?: string;
proprietaryIssuer?: string;
proprietaryCode?: string;
}