diff options
Diffstat (limited to 'libeufin/iso20022.rst')
-rw-r--r-- | libeufin/iso20022.rst | 215 |
1 files changed, 194 insertions, 21 deletions
diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index a7d90586..06d929c2 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -5,35 +5,208 @@ 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 -Cash Management (camt) -====================== +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. -camt.052: Bank to Customer Account Report ------------------------------------------ +The specifics of this mapping are: -* pending and booked transaction + * 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. -Schema versions: -* GLS uses camt.052.001.02 +Why does LibEuFin not use ISO 20022? +==================================== -.. code-block:: none +While LibEuFin can ingest ISO 20022 messages (camt.05x, pain.002) and generate +them (pain.001), it does not use ISO 20022 in its API and internal data model. - + Document/BkToCstmrAcctRpt - ++ GroupHeader [1..1] - ++ Report [1..*] - +++ Account [1..1] - +++ Balance [1..*] - +++ Entry [1..*] - ++++ Amount [1..1] - ++++ Status [1..1] - ++++ EntryDetails [1..1] +Reasons for not using ISO 20022 directly are: +1. Impedence mismatch. ISO 20022 messages do not map well to query/response + APIs. +2. Cumbersome to use. Even when ISO 20022 messages are directly mapped + to JSON, they are difficult to use due to their verbosity. +3. Underspecification. Messages like camt.05x leave many "degrees of freedom" + when translating the underlying data into a message. +4. No interoperability. As a result of underspecification, different countries/organisations + define their own subset and interpretation rules for ISO 20022 messages. This can + lead to even contradictory usage rules. An example for this is how the Swiss and EPC + interpretations handle transaction amounts in the presence of multiple currencies. +5. Redundancy. ISO 20022 are redundant, and often mix aspects of the "presentation logic" + with the underlying data model. An example of this is the optional "summary" information + in camt.05x messages. -camt.053: Bank to Customer Statement ------------------------------------- +Instead of using ISO 20022 messages directly, LibEuFin leverages the standard in other ways: -* only booked transactions -* only for the last day (?) +* As the data exchange format with banks +* As a guideline for naming in data formats +* As a guideline for which concepts need to be understood by LibEuFin + + +Implementation notes for camt.05x +================================= + +Types of amounts in camt messages +--------------------------------- + +* Entry amount + + * ISO 20022: Mandatory, with debit/credit indicator. Indicates money + moving in/out of the account in the account's currency. + * LibEuFin: Same. + +* Entry transaction amount + + * 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. + +* Entry instructed amount + + * 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. + +* Entry counter value amount + + * ISO 20022: Optional, direction-less. Amount in the account's + currency before charges. + * LibEuFin: Same. + +* Entry announced posting amount + + * (not used by LibEuFin) + +* EntryDetails amount + + * ISO 20022: Optional, with debit-credit indicator. Same as "Entry amount" + but for EntryDetails (= logical transactions). + * LibEuFin: Always present. In Swiss camt messages, the element is always + present. In German/Swedish/... camt, we take the "Entry amount" for + non-batch entries, whereas in batch entries we use the "EntryDetails + transaction amount" with the same debit credit indicator as the whole + entry, which by local rules is always in the bank account currency. + +* EntryDetails (transaction / instructed / counter value) amount + + * ISO 20022: Optional, direction-less. Same as "Entry ... amount" + but for EntryDetails (= logical transactions). + * Same. + +* EntryDetails announced posting amount + + * (not used by LibEuFin) + + +LibEuFin schema for account history +----------------------------------- + +FIXME: This is not complete yet. + +.. code-block:: typescript + + 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; + } |