summaryrefslogtreecommitdiff
path: root/libeufin
diff options
context:
space:
mode:
Diffstat (limited to 'libeufin')
-rw-r--r--libeufin/api-nexus.rst567
-rw-r--r--libeufin/api-sandbox.rst261
-rw-r--r--libeufin/architecture.rst58
-rw-r--r--libeufin/bank-transport-ebics.rst55
-rw-r--r--libeufin/banking-protocols.rst125
-rw-r--r--libeufin/concepts.rst160
-rw-r--r--libeufin/index.rst10
-rw-r--r--libeufin/iso20022.rst215
-rw-r--r--libeufin/sepa.rst24
-rw-r--r--libeufin/transaction-identification.rst85
10 files changed, 1226 insertions, 334 deletions
diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst
index 745182cf..d58b43bd 100644
--- a/libeufin/api-nexus.rst
+++ b/libeufin/api-nexus.rst
@@ -1,187 +1,536 @@
Nexus API
###########
+.. contents:: Table of Contents
HTTP API
========
-Users Management
-----------------
+Authentication
+--------------
-Users are the entity that access accounts. They do not necessarily correspond
-to the actual legal owner of an account. Their main purpose in the nexus is
-access management.
+Currently every request made to nexus must be authenticated using the *HTTP
+basic auth* mechanism.
-.. http:get:: <nexus>/users
+Other authentication mechanisms (e.g. OpenID Connect) might
+be supported in the future.
- List users.
+User Management
+---------------
- **Required permission:** Administrator.
+.. http:get:: {nexusBase}/user
-.. http:post:: <nexus>/users
+ Get information about the current user (based on the authentication information
+ in this request).
- Create a new user.
+ **Response:**
- **Required permission:** Administrators.
+ .. ts:def:: GetUserResponse
+ interface UserResponse {
-Bank Account Management
------------------------
+ // User name
+ username: string;
-.. http:get:: <nexus>/bank-accounts
+ // Is it a superuser?
+ superuser: boolean;
+ }
- List bank accouts managed by nexus.
+.. http:post:: {nexusBase}/users
+ Create a new user. Only a superuser can call this API.
-.. http:post:: <nexus>/bank-accounts
+ **Request:**
- List bank accouts managed by nexus.
+ The body is a `User` object.
+ **Response:**
-.. http:get:: <nexus>/bank-accounts/{acctid}/history
+ :status 409 Conflict: Username is not available.
- :query method: Method to query the bank transaction (cached, ebics, fints, ...)
+ **Details:**
- Query the transaction history of an account via the specified method.
+ .. ts:def:: User
+ interface User {
-.. http:get:: <nexus>/bank-accounts/{acctid}/payments
+ // User name
+ username: string;
- List payments made with this bank account via nexus.
+ // Initial password
+ password: string;
+ }
-.. http:post:: <nexus>/bank-accounts/{acctid}/payments
- Initiate a payment.
+.. http:get:: {nexusBase}/users
+ Return list of users.
-Low-level EBICS API
--------------------
+Bank Accounts
+-------------
-.. http:post:: <nexus>/ebics/subscribers/{id}/backup
+The LibEuFin maintains a copy of the bank account transaction history and balance information,
+manages payment initiations of the account and tracks the of payment initiations.
+
+.. http:get:: {nexusBase}/bank-accounts
- Ask the server to export the three keys, protected with passphrase.
+ **Response:**
- .. ts:def:: NexusEbicsBackupRequest
-
- interface NexusEbicsBackupRequest {
- passphrase: string;
- }
+ A list of `BankAccount` objects
+ that belong to the requester.
+ .. ts:def:: BankAccount
+
+ interface BankAccount {
+ // mnemonic name identifying this bank account.
+ nexusBankAccountId: string;
+ // IBAN
+ iban: string;
+ // BIC
+ bic: string;
+ // Legal subject owning the account.
+ ownerName: string;
+ }
- .. ts:def:: NexusEbicsBackupResponse
+.. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit
- interface NexusEbicsBackupResponse {
-
- // The three passphrase-protected private keys in the PKCS#8 format
+ Ask nexus to submit one prepare payment at the bank.
+
+ :status 404 Not Found: the unique identifier **or**
+ the bank connection could not be found in the system
+
+
+.. http:get:: {nexus}/bank-accounts/{my-acct}/payment-initiations/{uuid}
+
+ Ask the status of payment ``$uuid``.
+
+ **Response:**
+
+ .. ts:def:: PaymentStatus
+
+ interface PaymentStatus {
+
+ // Payment unique identifier
+ uuid: string;
+
+ // True for submitted payments
+ submitted: boolean;
+
+ // Creditor IBAN
+ creditorIban: string;
+
+ // Creditor BIC
+ creditorBic: string;
+
+ // Creditor legal name
+ creditorName: string;
+
+ // Amount
+ amount: string;
+
+ // Subject
+ subject: string;
+
+ // Date of submission (in dashed form YYYY-MM-DD)
+ submissionDate: string;
+
+ // Date of preparation (in dashed form YYYY-MM-DD)
+ preparationDate: string;
+ }
+
+.. http:get:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations
+
+ Ask nexus the list of initiated payments. At this stage of the API,
+ **all** is returned: submitted and non submitted payments.
+
+ **Response**
+
+ .. ts:def:: InitiatedPayments
+
+ interface InitiatedPayments {
+
+ // list of all the initiated payments' UID.
+ initiatedPayments: PaymentStatus[];
+ }
+
+
+.. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations
+
+ Ask nexus to prepare instructions for a new payment.
+ Note that ``my-acct`` is the bank account that will be
+ **debited** after this operation.
+
+ **Request:**
+
+ .. ts:def:: PreparedPaymentRequest
+
+ interface PreparedPaymentRequest {
+ // IBAN that will receive the payment.
+ iban: string;
+ // BIC hosting the IBAN.
+ bic: string;
+ // Legal subject that will receive the payment.
+ name: string;
+ // payment subject.
+ subject: string;
+ // amount, in the format CURRENCY:XX.YY
+ amount: string
+ }
+
+ **Response:**
+
+ .. ts:def:: PreparedPaymentResponse
+
+ interface PreparedPaymentResponse {
+
+ // Opaque identifier to be communicated when
+ // the user wants to submit the payment to the
+ // bank.
+ uuid: string;
+ }
+
+.. http:post:: {nexusBase}/bank-accounts/{acctid}/fetch-transactions
+
+ Nexus will download bank transactions using the given connection.
+
+ **Request:**
+
+ .. ts:def:: CollectedTransaction
+
+ interface CollectedTransaction {
+ // Optional field to specify the bank connection to
+ // use for such operation.
+ bankConnection?: string;
+ // dashed date (YYYY-MM-DD) of the earliest payment
+ // in the result. Optional, defaults to "earliest
+ // possible" date.
+ start: string;
+ // dashed date (YYYY-MM-DD) of the earliest payment
+ // in the result. Optional, defaults to "latest
+ // possible" date.
+ end: string;
+ }
+
+.. http:get:: {nexusBase}/bank-accounts/{acctid}/transactions
+
+ Shows which transactions are stored locally at nexus.
+
+ **Query parameters:**
+
+ * **start** start (dashed YYYY-MM-DD) date of desired payments.
+ Optional, defaults to "earliest possible" date
+ * **end** end (dashed YYYY-MM-DD) date of desired payments.
+ Optional, defaults to "earliest possible" date
+
+
+ **Response:** A list of `Transaction` objects.
+
+ .. ts:def:: Transaction
+
+ interface Transaction {
+ // local bank account involved in the transaction.
+ account: string;
+
+ // counterpart IBAN
+ counterpartIban: string;
+
+ // counterpart BIC
+ counterpartBic: string;
+
+ // counterpart holder name
+ counterpartName: string;
+
+ // amount, in the format [-]CURRENCY:XX.YY,
+ // where the minus sign as prefix indicates
+ // a debit for the user's bank account.
+ amount: string;
+
+ // Dashed date YYYY-MM(01-12)-DD(01-31) of the transaction.
+ date: string;
+
+ // Payment subject.
+ subject: string;
+ }
+
+
+Bank Connections
+----------------
+
+Bank connections connect the local LibEuFin bank account
+to the real bank.
+
+.. http:post:: <nexus>/bank-connections
+
+ Activate a new bank connection for the requesting user.
- authBlob: string; // base64
- encBlob: string; // base64
- sigBlob: string; // base64
- hostID: string;
- userID: string;
- partnerID: string;
- ebicsURL: string;
- }
+ **Request:**
+ .. ts:def:: BankConnectionRestoreRequest
-.. http:post:: <nexus>/ebics/subscribers/{id}/restoreBackup
+ interface BankConnectionRestoreRequest {
+
+ source: "new" | "backup";
+
+ name: string;
+
+ // Restore a previous connection. Take precedence
+ // over the 'new' field.
+ backup?: BankConnectionBackup;
+
+ passphrase?: string;
+
+ // Data to create a fresh bank connection without
+ // restoring any backup.
+ data?: BankConnectionNew;
+ }
+
+
+ .. ts:def:: BankConnectionNew
+
+ interface BankConnectionNew {
+
+ // This type is strictly dependent on
+ // the connection being created. For Ebics,
+ // it will contain the required fields (as strings):
+ // 'ebicsURL', 'userID', 'partnerID', 'hostID', and
+ // the optional 'systemID'.
- Ask the server to restore the keys. Always creates a NEW
- "{id}" account, and fails if it exists already.
+ // Other connection types, like 'local' (used for testing
+ // purposes skipping any interaction with the bank service)
+ // and 'fints' are all work in progress!
+
+ }
+
+
+ .. ts:def:: BankConnectionBackup
+
+ interface BankConnectionBackup {
+
+ // The information needed in this type depend entirely
+ // on which connectionis being restored.
+
+ }
+
+ **Response:**
+
+ :status 409 Conflict: The ``name`` field exists already for
+ the requesting user.
- .. ts:def:: NexusEbicsRestoreBackupRequest
+.. http:post:: {nexusBase}/bank-connections/delete-connection
- interface NexusEbicsRestoreBackupRequest {
+ **Request:**
+
+ .. ts:def:: BankConnectionDeletion
+
+ interface BankConnectionDeletion {
+ // label of the bank connection to delete
+ bankConnectionId: string;
+ }
+
+.. http:get:: {nexusBase}/bank-connections
+
+ List available bank connections.
+
+
+.. http:get:: {nexusBase}/bank-connections/{connId}
+
+ Get information about one bank connection.
+
+ .. ts:def:: BankConnectionInfo
- // passphrase to decrypt the keys
- passphrase: string;
+ interface BankConnectionInfo {
+ bankConnectionId: string;
+
+ bankConnectionType: string;
+
+ // Is this bank connection ready, or
+ // are we waiting for the bank to activate
+ // the connection?
+ ready: boolean;
+
+ // Did the user review the bank's keys?
+ bankKeysReviewed: boolean;
+ }
+
+
+.. http:post:: {nexusBase}/bank-connections/{connId}/connect
+
+ Initialize the connection by talking to the bank.
- // The three passphrase-protected private keys in the PKCS#8 format
- authBlob: string; // base64
- encBlob: string; // base64
- sigBlob: string; // base64
- hostID: string;
- userID: string;
- partnerID: string;
- ebicsURL: string;
- }
+.. http:post:: {nexusBase}/bank-connections/{connId}/export-backup
- .. ts:def:: NexusEbicsCreateSubscriber
+ Make a passphrase-encrypted backup of this connection.
-.. http:post:: <nexus>/ebics/subscribers
+.. http:post:: {nexusBase}/bank-connections/{connId}/fetch-accounts
- Create a new subscriber. Create keys for the subscriber that
- will be used in later operations.
+ Update accounts that are accessible via this bank connection.
- .. ts:def:: NexusEbicsCreateSubscriber
+.. http:get:: {nexusBase}/bank-connections/{connId}/accounts
- interface NexusEbicsCreateSubscriber {
- ebicsUrl: string;
- hostID: string;
- partnerID: string;
- userID: string;
- systemID: string?
- }
+ List the bank accounts that this bank connection provides access to.
+ .. ts:def:: OfferedBankAccount
-.. http:get:: <nexus>/ebics/subscribers
+ interface OfferedBankAccount {
- List EBICS subscribers managed by nexus.
+ // Unique identifier for the offered account
+ offeredAccountId: string;
+ // IBAN of the offered account
+ iban: string;
-.. http:get:: <nexus>/ebics/subscribers/{id}
+ // BIC of the account's financial institution
+ bic: string;
- Get details about an EBICS subscriber.
+ // Account owner name
+ ownerName: string;
-.. http:get:: <nexus>/ebics/subscriber/{id}/keyletter
+ // If the account has been imported,
+ // this field contains the ID of the
+ // Nexus bank account associated with it.
+ nexusBankAccountId: string | null;
+ }
- Get a formatted letter (mark-down) to confirm keys via ordinary mail.
+.. http:post:: {nexusBase}/bank-connections/{connId}/import-account
-.. http:post:: <nexus>/ebics/subscriber/{id}/sendIni
+ Import a bank account provided by the connection into the Nexus.
- Send INI message to the EBICS host.
+ If no Nexus bank account with the ID ``nexusBankAccountId`` exists,
+ a new one will be created, and it will have ``connId`` as the
+ default bank connection.
-.. http:post:: <nexus>/ebics/subscriber/{id}/sendHia
+ If an existing Nexus bank account with the same ID already exists,
+ this connection will be added as an available connection for it.
+ This only succeeds if the bank account has the same IBAN.
- Send HIA message to the EBICS host.
+ .. ts:def:: ImportBankAccount
-.. http:get:: <nexus>/ebics/subscriber/{id}/sendHtd
+ interface ImportBankAccount {
- Send HTD message to the EBICS host.
+ // Identifier for the bank account, as returned by /accounts
+ // of the bank connection.
+ offeredAccountId: string;
-.. http:post:: <nexus>/ebics/subscriber/{id}/sync
+ // Nexus-local identifier for the bank account.
+ nexusBankAccountId: string;
+ }
- Synchronize with the EBICS server. Sends the HPB message
- and updates the bank's keys.
+Facades
+-------
-.. http:post:: <nexus>/ebics/subscriber/{id}/sendEbicsOrder
+.. http:get:: <nexus>/facades
- Sends an arbitrary bank-technical EBICS order. Can be an upload
- order or a download order.
+ List available facades.
- .. ts:def:: NexusEbicsSendOrderRequest::
+.. http:post:: {nexus}/facades
+
+ Create a new facade; it requires a `FacadeInfo` as the request's body.
+
+.. http:get:: {nexus}/facades/${fcid}
+
+ Get details about a facade.
+
+ .. ts:def:: FacadeInfo
+
+ interface FacadeInfo {
+ // Name of the facade, same as the "fcid" parameter.
+ name: string;
+
+ // Type of the facade.
+ // For example, "taler-wire-gateway".
+ type: string;
+
+ // Name of the user that created the facade.
+ // Whenever the facade accesses a resource it is allowed to
+ // access, the creator must *also* have access to that resource.
+ creator: string;
+
+ // Bank accounts that the facade has read/write
+ // access to.
+ bankAccountsRead: string[];
+ bankAccountsWrite: string[];
+
+ // Bank connections that the facade has read/write
+ // access to.
+ bankConnectionsRead: string[];
+ bankConnectionsWrite: string[];
+
+ // Facade-specific configuration details.
+ config: any;
+ }
+
+
+Bank Connection Protocols
+-------------------------
+
+.. http:get:: {nexus}/bank-connection-protocols
+
+ List supported bank connection protocols.
+
+.. http:post:: {nexus}/bank-connection-protocols/ebics/test-host
+
+ Check if the nexus can talk to an EBICS host.
+ This doesn't create a new connection in the database,
+ and is useful during setup when the user hasn't entered
+ the full details for the connection yet.
+
+ .. ts:def:: EbicsHostTestRequest
+
+ interface EbicsHostTestRequest {
+ ebicsBaseUrl: string;
+ ebicsHostId: string;
+ }
+
+
+EBICS-specific APIs
+-------------------
+
+The following endpoints are only available for EBICS bank connections.
+They are namespaced under the ``/ebics/`` sub-resource.
+
+.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/download/{msg}
+
+ .. warning::
+
+ Use with care. Typically only necessary for testing and debugging.
+
+ Perform an EBICS download transaction of type ``msg``.
+ This request will not affect any bank account or other state
+ in the nexus database. It will just make a request to the bank
+ and return the answer.
+
+.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/upload/{msg}
+
+ .. warning::
+
+ Use with care. Typically only necessary for testing and debugging.
+
+ Perform an EBICS upload transaction of type ``msg``.
+ This request will not affect any bank account or other state
+ in the nexus database. It will just make a request to the bank
+ and return the answer.
- interface NexusEbicsSendOrderRequest {
- // Bank-technical order type, such as C54 (query transactions)
- // or CCC (initiate payment)
- orderType: string;
- // Generic order parameters, such as a date range for querying
- // an account's transaction history.
- orderParams: OrderParams
+The taler-wire-gateway facade
+-----------------------------
- // Body (XML, MT940 or whatever the bank server wants)
- // of the order type, if it is an upload order
- orderMessage: string;
- }
+The ``taler-wire-gateway`` facade has the following configuration:
-.. http:post:: <nexus>/ebics/subscriber/{id}/ebicsOrders
+.. ts:def:: TalerWireGatewayFacadeConfig
+
+ interface TalerWireGatewayFacadeConfig {
+ // Bank account and connection that is
+ // abstracted over.
+ bankAccount: string;
+ bankConnection: string;
- .. note::
+ // Corresponds to whether we trust C52, C53 or C54 (SEPA ICT)
+ // for incoming transfers.
+ reserveTransferLevel: "statement" | "report" | "notification";
- This one should be implemented last and specified better!
+ // Time between incremental requests
+ intervalIncremental: string;
- Return a list of previously sent ebics messages together with their status.
- This allows retrying sending a message, if there was a crash during sending
- the message.
+ // FIXME: maybe more scheduling parameters?
+ }
diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst
index ee298d85..f75c76e0 100644
--- a/libeufin/api-sandbox.rst
+++ b/libeufin/api-sandbox.rst
@@ -1,189 +1,164 @@
+
Sandbox API
###########
-Entities
+HTTP API
========
-Bank Account
- ...
+..
+ Payments.
-EBICS Host
+.. http:post:: /admin/payments
-EBICS Subscriber
- ...
+ Adds a new payment to the book. Mainly used for testing
+ purposes.
-EBICS Partner
- ...
+ **Request:**
+ .. ts:def:: PaymentRequest
+ interface PaymentRequest {
+
+ // IBAN that will receive the payment.
+ creditorIban: string;
-HTTP API
-========
+ // IBAN that will send the payment.
+ debitorIban: string;
+ amount: string;
+ currency: string;
-.. http:post:: /ebicsweb
+ // subject of the payment.
+ subject: string;
+ }
- Submit an EBICS request to the sandbox.
+..
+ Host management.
+.. http:post:: /admin/ebics/hosts
+
+ Creates a new Ebics host.
-.. http:post:: /admin/customers
+ **Request:**
- Create a new customer. A customer identifies a human that
- may own multiple bank accounts.
+ .. ts:def:: EbicsHostRequest
- When creating a customer, one EBICS subscriber is automatically
- created for the customer.
+ interface EbicsHostRequest {
+
+ // Ebics version.
+ hostID: string;
- In the future, we might add an API to create multiple additional subscribers for
- a customer.
+ // Name of the host.
+ ebicsVersion: string;
+ }
+
- When creating a new customer, an ID will be assigned automatically.
+.. http:get:: /admin/ebics/hosts
+
+ Shows the list of all the hosts existing
+ in the system.
- .. code-block:: tsref
+ **Response:**
- interface CustomerCreationRequest {
- // human-readable name for the customer
- name: string;
- }
+ .. ts:def:: EbicsHostResponse
-.. http:get:: /admin/customers/:id
+ interface EbicsHostResponse {
+
+ // shows the host IDs that are active in the system.
+ // The Ebics version *is* missing, but it's still available
+ // via the HEV message.
+ ebicsHosts: string[];
+ }
+
- Get information about a customer.
+..
+ Subscriber management.
- .. ts:def:: CustomerInfo
+.. http:post:: /admin/ebics/subscribers
- interface CustomerInfo {
- ebicsInfo?: CustomerEbicsInfo;
- finTsInfo?: CustomerFinTsInfo;
- }
+ Creates a new Ebics subscriber.
- .. ts:def:: CustomerEbicsInfo
+ **Request:**
- interface CustomerEbicsInfo {
- ebicsHostId: string;
- ebicsParterId: string;
- ebicsUserId: string;
+ .. ts:def:: SubscriberRequest
- // Info for the customer's "main subscriber"
- subscriberInitializationState: "NEW" | "PARTIALLY_INITIALIZED_INI" | "PARTIALLY_INITIALIZED_HIA" | "READY" | "INITIALIZED";
- }
+ interface SubscriberRequest {
+
+ // hostID
+ hostID: string;
- .. ts:def:: CustomerFinTsInfo
-
- // TODO
+ // userID
+ userID: string;
-.. http:post:: /admin/customers/:id/ebics/keyletter
+ // partnerID
+ partnerID: string;
- Accept the information from the customer's ("virtual") INI-Letter and HIA-Letter
- and change the key's state as required.
+ // systemID
+ systemID: string;
- .. code-block:: tsref
+ }
+
- interface KeyLetterRequest {
+.. http:get:: /admin/ebics/subscribers
- ini: {
- // The user ID that participates in a EBICS subscriber.
- userId: string;
+ Shows the list of all the subscribers existing
+ in the system.
- // The customer ID specific to the bank (therefore not
- // participating in a EBICS subscriber).
- customerId: string;
+ **Response:**
- // Human name of the user
- name: string;
+ .. ts:def:: SubscribersResponse
- // As per specification, this value is:
- // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format.
- date: string;
+ interface SubscribersResponse {
+
+ subscribers: Subscriber[]
+ }
+
+ .. ts:def:: Subscriber
- // As per specification, this value is:
- // "Time of processing of the corresponding EBICS order". HH:MM:SS format.
- time: string;
+ interface Subscriber {
+
+ // userID
+ userID: string;
- // Identification token of the bank. Not required to obey to any particular standard.
- recipient: string;
+ // partnerID
+ partnerID: string;
- // Electronic signature version. Admitted values: A005, A006.
- version: string;
+ // hostID
+ hostID: string;
- // Length in bits of the key exponent.
- public_exponent_length: number;
- // RSA key exponent in hexadecimaml notation.
- public_exponent: string;
+ }
- // Length in bits of the key modulus.
- public_modulus_length: number;
- // RSA key modulus in hexadecimaml notation.
- public_modulus: string;
+.. http:post:: /admin/ebics/bank-accounts
- // RSA key hash.
- //
- // A005, A005 versions require hash type SHA-256.
- hash: string;
- }
+ Associates a new bank account to an existing subscriber.
- hia: {
- // The user ID that participates in a EBICS subscriber.
- userId: string;
-
- // The customer ID specific to the bank (therefore not
- // participating in a EBICS subscriber).
- customerId: string;
-
- // Human name of the user
- name: string;
-
- // As per specification, this value is:
- // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format.
- date: string;
-
- // As per specification, this value is:
- // "Time of processing of the corresponding EBICS order". HH:MM:SS format.
- time: string;
-
- // Identification token of the bank. Not required to obey to any particular standard.
- recipient: string;
-
- ////////////////////////////////////////////////////
- // Identification and Authentication key details. //
- ////////////////////////////////////////////////////
-
- // Identification and authentication signature version.
- // Admitted value: X002.
- ia_version: string;
-
- // length of the exponent, in bits.
- ia_public_exponent_length: number;
- // RSA key exponent in hexadecimaml notation.
- ia_public_exponent: string;
-
- // length of the modulus, in bits.
- ia_public_modulus_length: number;
- // RSA key modulus in hexadecimaml notation.
- ia_public_modulus: string;
-
- // SHA-256 hash of the identification and authentication key.
- ia_hash: string;
-
- /////////////////////////////
- // Encryption key details. //
- /////////////////////////////
-
- // Encryption version. Admitted value: E002.
- enc_version: string;
-
- // length of the exponent, in bits.
- enc_public_exponent_length: number;
- // RSA key exponent in hexadecimaml notation.
- enc_public_exponent: string;
-
- // length of the modulus, in bits.
- enc_public_modulus_length: number;
- // RSA key modulus in hexadecimaml notation.
- enc_public_modulus: string;
-
- // SHA-256 hash of the encryption key.
- enc_hash: string;
- }
- }
+ **Request:**
+
+ .. ts:def:: BankAccountRequest
+
+ interface BankAccountRequest {
+
+ // Ebics subscriber
+ subscriber: string;
+
+ // IBAN
+ iban: string;
+
+ // BIC
+ bic: string;
+
+ // human name
+ name: string;
+
+ // bank account label
+ label: string;
+
+ }
+
+..
+ Main EBICS service.
+
+.. http:post:: /ebicsweb
+
+ Serves all the Ebics requests.
diff --git a/libeufin/architecture.rst b/libeufin/architecture.rst
deleted file mode 100644
index e5cad890..00000000
--- a/libeufin/architecture.rst
+++ /dev/null
@@ -1,58 +0,0 @@
-LibEuFin Architecture
-#####################
-
-Sandbox
-=======
-
-* the sandbox's EBICS API emulates the behavior of a real bank's EBICS
- interface
-
-* *(Only in the future)*: FinTS API and other FinTech APIs
-
-* the sandbox's management API allows an administrator to:
-
- * create new **bank** accounts
- * create new **EBICS subscriber** accounts
-
- * a subscriber has (optionally?) a SystemID (for technical subscribers),
- a UserID and a PartnerID
- * each bank account has a list of subscribers than can access it
-
- * delete accounts
- * ...
-
-* the sandbox's "miscellaneous" API provides public functionality that is not covered
- directly by EBICS, such as:
-
- * a way to get the transactions in form of a JSON message, to check if it matches the EBICS response
-
- * you could call it a "reference history"
-
- * publicly accessible key management functionality, for example for the EBICS INI process
-
- * this is the "electronic version" of sending an HIA/INI letter
-
-* things that we do **not** want to implement right now:
-
- * Distributed electronic signatures. For now, it is enough for every order
- to be signed just by one authorized subscriber.
-
-Nexus
-=====
-
-The Nexus takes JSON requests and translates them into API calls for the
-respective real bank accounts (EBICS, FinTS, ...). It also stores the bank
-transaction history to enable a linearlized view on the transaction history
-with unique transaction identifier, which some of the underlying banking APIs
-don't provide directly.
-
-``libeufin-nexus-httpd`` is the binary (or wrapper around the Java invocation)
-that runs the HTTP service.
-
-
-CLI Tools
-=========
-
-The Sandbox and Nexus are only HTTP services. The CLI tools are used to
-actually access them.
-
diff --git a/libeufin/bank-transport-ebics.rst b/libeufin/bank-transport-ebics.rst
new file mode 100644
index 00000000..0d06f83b
--- /dev/null
+++ b/libeufin/bank-transport-ebics.rst
@@ -0,0 +1,55 @@
+The EBICS Bank Transport
+========================
+
+An EBICS bank transport in LibEuFin conceptually corresponds
+to the "EBICS Subscriber" in EBICS terminology.
+
+
+Bank Transport Setup
+--------------------
+
+The following steps are required to set up an EBICS bank transport:
+
+1. The bank must set up the EBICS access for the user.
+ The bank will notify the user of the following parameters:
+
+ * the URL of the EBICS server used by the bank
+ * the HostID of the bank within the EBICS server (sometimes one EBICS server hosts multiple banks)
+ * the PartnerID (typically identifies the owner of the bank account within the banking system)
+ * the UserID (typically identifies the person that accesses the bank account, can be different from the owner)
+ * the SystemID (optional and rarely used, basically a "sub-identity" of a subscriber when multiple technical
+ systems have access to the account via EBICS)
+
+2. The user enters the information from the list above in the setup dialog in the LibEuFin nexus (UI/CLI).
+
+3. The LibEuFin nexus generates cryptographic key material (3 RSA key pairs)
+
+5. The nexus sends the public keys electronically to the bank's EBICS server, together with the information
+ identifying the subscriber (PartnerID, UserID, SystemID).
+
+6. The user print a document that contains the public key and hashes for all three key pairs.
+ The user then signs this document sends it to the bank (physically/scanned).
+
+7. The bank receives the letter and verifies that the keys from the letter correspond
+ to the electronically sent keys. If they match, the bank sets the state of the
+ subscriber to "ready".
+
+8. The user now has to wait until the bank has set the EBICS subscriber state to "ready".
+ There is no in-band notification for this, but the Nexus can try downloading the bank's
+ cryptographic parameters. This will only succeed once the EBICS subscriber is set to "ready"
+ by the bank.
+
+9. The user should confirm the public keys of the bank received in the previous step.
+ Typically the bank gives the value of these public keys in an out-of-band channel.
+
+10. Now the user can finally use the EBICS bank transport. The first step after finishing
+ the setup should be to import the bank accounts accessible for this EBICS subscriber.
+
+
+Alternative ways of setting up the EBICS bank transport are:
+
+* Importing from a backup. The backup contains metadata (EBICS URL, HostID,
+ UserId, ...) and the three passphrase-protected subscriber keys.
+* Certificate-based setup (currently not supported by LibEuFin, only used in France)
+
+
diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst
new file mode 100644
index 00000000..17dda0b9
--- /dev/null
+++ b/libeufin/banking-protocols.rst
@@ -0,0 +1,125 @@
+Banking Protocols
+#################
+
+This page collects information we have about banking protocols available around
+the world.
+
+
+Open Financial Exchange (OFX) Direct Connect
+============================================
+
+`OFX <https://www.ofx.net/>`__ is widely used in the US. It defines a completely
+custom protocol (based on HTTP) and data formats (**not** based on ISO20022) for banking.
+
+
+Electronic Banking Internet Communication Standard (EBICS)
+==========================================================
+
+EBICS is used primarily in Germany, France and Switzerland. Some banks (such as BNPParibas
+with their `Global Ebics <https://cashmanagement.bnpparibas.com/our-solutions/solution/global-ebics>`__)
+also allow EBICS access to accounts in other countries.
+
+EBICS is just a transfer layer for communicating with banks. Banks define what
+messages they support. In practice, EBICS is very often used to transfer
+ISO20022 messages.
+
+German banks that are part of the German Banking Industry Committee all must offer EBICS access.
+Thus this protocol is a good choice for the German market.
+
+
+FinTS / HBCI
+============
+
+German home-banking standard. FinTS is the successor of the Home Banking
+Computer Interface (HBCI), but older versions of FinTS are often still called
+HBCI.
+
+The current version, FinTS 4.0, is not widely supported by banks yet. Starting with FinTS,
+XML is used as a data format. Previous versions used a custom text/binary format.
+
+Only some banks allow authentication based on key pairs.
+Due to different interpretation of PSD2, other banks now only allow authentication
+methods that require interaction from the customer (SCA / Strong Customer Authentication).
+
+Payloads these days can be ISO20022 messages.
+
+Examples:
+ * `GLS <https://www.gls.de/geschaefts-firmenkunden/zahlungsverkehr/onlinebankingverfahren-und-programme/daten-zum-onlinebanking/>`__
+
+
+PSD2
+====
+
+PSD2 is not a technical standard, but high-level legal requirements on (amongst other things) APIs
+that banks have to offer.
+
+There are many implementations of PSD2 APIs. The `Berlin Group <https://www.berlin-group.org/>`__
+provides a framework that somewhat standardizes technical details, but the use of this standard
+is by no means necessary.
+
+Unfortunately, it focuses on *other* parties accessing *your* bank account. It
+does not give customers access to their own bank account. Customers can manage
+third party access they give to their bank account in their online banking
+system. That mechanism is conceptually similar to OAuth2. In fact, some
+implementations of PSD2 even use OAuth2 directly.
+
+PSD2 APIs usually use JSON as a data format. Often the schema and terminology is "inspired" by ISO20022
+messages, but no actual ISO20022 XML message formats are used.
+
+PSD2 requires two main services to be available via an API:
+
+* AIS (Account Information Service).
+* PIS (Payment Initiation Service).
+
+Together, they're often called XS2A ("access to account").
+
+An entity that wants to use AIS has to be registered with the financial
+oversight authority in its country (BAFIN in Germany). PIS has even stronger
+legal prerequisites.
+
+On a technical level, using PSD2 APIs usually requires having an `EIDAS <https://en.wikipedia.org/wiki/EIDAS>`__ certificate.
+
+Examples (bank offerings):
+ * `Sparkasse <https://xs2a.sparkassen-hub.com/home>`__ (Berlin Group based)
+ * `Deutsche Bank <https://developer.db.com/products/psd2>`__
+
+Examples (standards):
+ * `STET PSD2 API <https://www.stet.eu/en/psd2/>`__
+ * `Berlin Group NextGenPSD2 <https://www.berlin-group.org/nextgenpsd2-downloads>`__
+
+
+
+Bank-Proprietary APIs
+=====================
+
+Some banks offer completely custom APIs to access services of the bank. These often include services
+not available via more standardized APIs, such as account creation.
+
+Often banks frame PSD2 as just another API available in their portfolio of API offerings.
+
+Examples:
+
+* `Deutsche Bank <https://developer.db.com/products>`__
+* `ING Group <https://developer.ing.com/api-marketplace/marketplace>`__
+* `Revolut <https://revolut-engineering.github.io/api-docs/business-api/>`__
+* `PayPal <https://developer.paypal.com/classic-home/>`__
+
+
+Open Bank Project
+=================
+
+The `Open Bank Project <https://www.openbankproject.com/>`__ provides a free software implementation of
+banking middleware that supports various APIs, including PSD2-compatible APIs (based on Berlin Group).
+
+API Docs: https://github.com/OpenBankProject/OBP-API/wiki/Open-Bank-Project-Architecture
+
+
+UK Open Banking
+===============
+
+Open Banking is the (quite confusing!) name of a UK-based open banking initiative.
+
+What's nice about Open Banking is that their APIs are really close to ISO 20022, unlike many
+similar HTTP+JSON APIs.
+
+https://openbanking.atlassian.net/wiki/spaces/DZ/pages/16385802/Specifications
diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst
new file mode 100644
index 00000000..da48d7f8
--- /dev/null
+++ b/libeufin/concepts.rst
@@ -0,0 +1,160 @@
+###################
+Conceptual Overview
+###################
+
+
+What is LibEuFin
+================
+
+The goal of LibEuFin is to make the development and testing of
+FinTech applications easier. It hides implementation details
+of complex legacy banking APIs behind a simple interface.
+
+LibEuFin Nexus and Sandbox
+--------------------------
+
+LibEuFin has two main components:
+
+1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific
+ format via an HTTP API. It then translates those requests into interactions
+ with other banking APIs, abstracting away different underlying protocols and
+ hiding the complexity of the legacy protocols used by some banks.
+
+2. The LibEuFin sandbox implements the server side of protocols
+ that banks speak. It also emulates a *very*, *very* simple
+ core banking system to manage accounts and their balance.
+ The main use case for the sandbox is testing LibEuFin itself,
+ as well as applications developed with LibEuFin.
+ The sandbox has a JSON API to set it up for tests (creating bank
+ hosts, bank accounts, fake transactions).
+
+
+High-Level Concepts
+===================
+
+Nexus Users
+-----------
+
+The concept of a *nexus user* is used to implement access control to the
+operations that the nexus provides.
+
+A user has a login name and a (salted, hashed) password. (Other authentication
+methods could be added in the future.)
+
+A nexus user can be marked as *superuser*. All permission checks are skipped
+for superusers. Only superusers are allowed to create/modify other users.
+
+Bank Accounts
+-------------
+
+A bank account is the local representation of some bank account.
+The information stored about it includes:
+
+* Local alias ("nickname") of the bank account
+* Account identification (IBAN / BIC / account holder)
+* A local mirror of the bank transaction history
+* Payment requests, i.e. payments that have been locally requested, together
+ with their state (sent or not sent, acknowledged in bank statement or not).
+* Error reports (e.g. failed payment requests, bank statement items that were not understood
+ by LibEuFin)
+* A default bank connection (if configured) that is used by default
+ for operations on the account
+* Other enabled bank connections
+
+Examples:
+
+.. code:: none
+
+ # Download latest transactions via the default bank connection and store them locally
+ curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-accounts/my-acct/collect-transactions
+
+Bank Connections
+----------------
+
+Bank connections connect the local LibEuFin bank account to the real bank.
+The bank connection includes the following data:
+
+* Local alias ("nickname") of the bank connection
+* the type of connection, i.e. the protocol used (EBICS, FinTS, loopback, sandbox)
+* protocol configuration (hostname, port, protocol sub-version/flags)
+* credentials to use the connection (e.g. password, EBICS subscriber keys)
+
+Bank connections provide the following actions:
+
+* Initial setup of the connection
+
+* Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ)
+
+ * These actions do not have any effect on the LibEuFin local bank account.
+ To persist changes to the local bank account (transaction history, payment request status),
+ the bank connection must be invoked via the bank account.
+
+* Import bank accounts
+
+ * Some bank connection protocols allow LibEuFin to query a list of bank
+ accounts that the connection has access to. This makes setup easier,
+ as the user doesn't have to create the local bank account manually.
+
+Examples:
+
+.. code:: none
+
+ # Manually request the inter-day account report via the EBICS C52 order
+ curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connections/my-ebics-testacct/send-c52
+
+ # Download available bank accounts that can be accessed through this connection,
+ # according to the bank server (with EBICS, does a HTD request).
+ # For each of them, create a bank account resource in LibEuFin.
+ curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connection/my-ebics-testacct/import-accounts
+
+Facades
+-------
+
+Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts
+and bank connections. Facades store the following information:
+
+* Local name of the facade
+* Facade type and options specific to the type
+* Associated bank accounts and bank connections that can be accessed by the layer
+* Internal tables used by the facade (i.e. facades are stateful)
+
+The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer.
+It provides a filtered view on the transaction history, a more restricted API to create payment
+requests, and a mechanism to create a counter-transaction for incoming transaction that do
+not conform to a certain format.
+
+Examples:
+
+.. code:: none
+
+ # Request the Taler-specific history through the facade
+ curl $AUTHEADER https://example1.libeufin.tech/facades/my-taler-wire-gw/api/history/incoming
+
+Access Control
+==============
+
+The goal of access control in LibEuFin is to allow the following scenarios:
+
+* The Nexus can be used by multiple clients for different bank accounts/connections
+ and these users can't access each other's bank accounts
+* For monitoring / dashboard (e.g. Taler rejected transactions, blacklists),
+ some users should only be able to have read-only access.
+
+It is currently not planned to have more fine-grained permissions, such as
+spending limits or more fine-grained read/write permissions.
+
+Users can be normal users or superusers. Permission checks do not apply to superusers,
+and only superusers can create other users.
+
+Each top-level object (bank account, bank connection, facade) has a list of
+nexus users with write access, and a list of users with read access.
+
+When using a bank connection through a bank account, permission checks must
+succeed for both the bank account and the bank connection
+
+This works differently for facades: A facade has a set of associated bank connections
+and bank accounts it can access. Permissions on these associated objects
+are checked when the facade is *created*. When invoking operations on the facade,
+the nexus only checks if the current nexus user can access the facade and *not* the
+underlying objects abstracted by the facade.
+
diff --git a/libeufin/index.rst b/libeufin/index.rst
index 62af14b4..766410e2 100644
--- a/libeufin/index.rst
+++ b/libeufin/index.rst
@@ -6,8 +6,12 @@ LibEuFin is a project providing free software tooling for European FinTech.
.. toctree::
:glob:
- ebics
- architecture
- api-sandbox
+ concepts
+ bank-transport-ebics
api-nexus
+ api-sandbox
+ ebics
+ sepa
iso20022
+ banking-protocols
+ transaction-identification
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;
+ }
diff --git a/libeufin/sepa.rst b/libeufin/sepa.rst
new file mode 100644
index 00000000..9555256a
--- /dev/null
+++ b/libeufin/sepa.rst
@@ -0,0 +1,24 @@
+SEPA Payments
+#############
+
+This page collects reference materials and details for specifics of SEPA payments.
+
+SEPA Credit Transfer (SCT)
+==========================
+
+SCT is a "normal" bank transfer. Details (terminology, data definitions, flow diagrams) can be found in the EPC's
+`SCT rulebook <https://www.europeanpaymentscouncil.eu/document-library/rulebooks/sepa-credit-transfer-rulebook>`__.
+
+
+Reject vs Return vs Recall
+--------------------------
+
+* A **rejected** payment is refused by the originator bank or the
+ clearing and settlement layer.
+* A **returned** payment is refused by the beneficiary's bank via a
+ counter-transaction over the settlement layer.
+* A payment is **recalled** when the originator's bank (potentially
+ requested by the originator) wants to "undo" a SCT.
+
+SEPA currently does **not** directly support a mechanism for the **beneficiary** to return
+a payment.
diff --git a/libeufin/transaction-identification.rst b/libeufin/transaction-identification.rst
new file mode 100644
index 00000000..7c737fc2
--- /dev/null
+++ b/libeufin/transaction-identification.rst
@@ -0,0 +1,85 @@
+Transaction Identification
+##########################
+
+This page describes how bank transactions are **identified** in various banking protocols and
+data formats.
+
+**Why is transaction identification necessary?**
+When a client downloads the transaction history from some data source, it has to know
+whether a transaction is new, or whether the transaction is already part of the
+client's local records.
+
+Protocol-specific Details
+=========================
+
+ISO 20022 camt.05X
+------------------
+
+The camt52/53/54 messages defined by ISO 20022 do not have a mandatory transaction
+identifier. Instead if defines a handful of optional references.
+
+Two identifiers seem to be used in practice: The *Account Servicer Reference* and the
+*Entry Reference*. Of these, only the *Account Servicer Reference* seems to be useful
+for transaction identification.
+
+The Account Servicer Reference is assigned by the bank to a transaction. In
+practice, all banks assign the **same** Account Servicer Reference to the same
+transaction showing up in camt52 (the account report), camt53 (the account
+statement) and camt53 (credit notifications).
+
+The Account Servicer Reference is assigned by the bank that reports the transaction,
+and does **not** serve as a globally unique identifier for the transaction.
+
+However, in rare cases, a transaction can be reported that does not yet have an
+Account Servicer Reference assigned to it by the bank yet. This can happen
+when the bank only received a (SWIFT) pre-notification for the transaction, but decides
+to already pass on this information to the customer. In this case, banks seem to
+assign an *Entry Reference* to the corresponding entry.
+
+Most other transactions, however, do **not** have an *Entry Reference* assigned to it.
+Some banks document that the *Entry Reference* is only unique within one report for one account.
+
+OFX
+---
+
+OFX assigns a transaction identifier to each reported transactions, allowing the client
+to know which transactions it has already seen.
+
+Problems and Possible Solutions
+===============================
+
+Sometimes the same bank can offer **multiple** ways to download transactions.
+In Germany, most banks offer EBICS and FinTS access, which delivers transactions
+in the camt.52/53 format. However, some also offer access via PSD2 APIs and completely custom APIs.
+
+Two APIs from the same bank do not necessarily need to support the same transaction identification scheme.
+This could lead to the same transaction showing up multiple times in the account transaction history, which
+is clearly bad!
+
+LibEuFin intends to solve this problem in the following ways:
+
+1. Each local account has a single "transaction identification scheme".
+ Importing transactions via a bank connection that has a different transaction
+ identifier scheme will fail.
+2. When a bank connection reports a transaction that is missing the expected transaction identifier,
+ the status (booked, pending, info) is examined:
+
+ 1. When the status is booked, an error is reported, and corresponding bank message
+ will be made available for review
+ 2. When the status is "pending" or "info", the entry will simply be ignored.
+
+In the future, this might be extended to be less restrictive:
+
+* An account could be configured to do transaction identification based on a "core attributes hash",
+ i.e. a cryptographic hash of core attributes of the transactions that are expected to not change.
+ This should only apply to booked transactions.
+* Un-identifiable pending/info transactions could be managed in a separate
+ "informational" transactions table that is purged as soon as a *booked statement closing transaction*
+ is reported with a higher booking date.
+
+Others
+======
+
+* `UETR <https://www.swift.com/your-needs/industry-themes/unique-end-to-end-transaction-reference-uetr>`__ is
+ a unique identifier used on the SWIFT level. It doesn't help for transaction identification
+ as not every transaction goes over SWIFT, even for SEPA accounts.