summaryrefslogtreecommitdiff
path: root/libeufin/transaction-identification.rst
blob: 7c737fc263d0622aff8ed0adeb1cd13fef1158f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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.