summaryrefslogtreecommitdiff
path: root/libeufin/iso20022.rst
diff options
context:
space:
mode:
Diffstat (limited to 'libeufin/iso20022.rst')
-rw-r--r--libeufin/iso20022.rst215
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;
+ }