Fetch and upate transactions
There are 2 relevant use cases for fetching and updating transactions. These are
- fetching transactions for a one-time assessment, and
- fetching and updating transactions for an on-going service.
This integration guide helps you to do either in the most efficient way to minimise authentication while optimise for retrieval of transaction data.
Fetch transactions
There are different approaches to fetching the transactions of one or multiple accounts.
If you want transactions from only 1 particular account (assuming the user has one or multiple to choose from) then we suggest using a single transaction flow.
If you want transactions from multiple accounts (potentially all accounts the user has access to) then we suggest starting with an accounts flow and iterating over the accounts which have the flag
capabilities.transactions.available
set totrue
with the transaction flow.
Both approaches will get you as many transactions as possible for your requested date range. This means if you plan to update the transactions after that, we recommend to then update only the last few days in any subsequent request.
In this integration guide, we will focus on the 2. approach.
Update transactions on a regular basis
NOTE: The consent_id and consent_token are required for updating transactions.
For updating transactions it is noteworthy to think of the right time span to update. Typically a transaction is processed within 1 to 3 business days. This means you get most newly added transactions if you request the last 3 business days. Since there are exceptions which can take longer it can be beneficial to update the last 7 days on private accounts and the last 90 days on business and/or corporate accounts.
Consent requests are error prone and we recommend to have a look at our guide to avoid early consent invalidation.
Fetching as many transactions as possible
Some banks limit the transaction history. Limits can apply to dates, meaning only the last 90 days, 6 or 12 months are available, or quantity, meaning only the last 1000 transactions.
Regardless of these differences, you should set your desired date range in a way that covers all your needs. We will return the maximum available transactions from the bank, but this might be less than what you requested.
Consent expiry and renewal
All consents are only valid for a certain period of time (lifetime), after which the consent expires and a new consent has to be generated. You can specify that maximum validity time of the consent in the consent_token
in the consent_scope.lifetime
of the session request.
Once the consent is expired, you receive CONSENT.EXPIRED
as a response to any request using the expired consent_token
. Now, the user has to grant access again, fetching a new consent.
To get a new consent, a new session has to be started. You can use the data from any previous session, e.g. IBANs, and provide them in the consent_scope
of the new session.
In short:
- Any consent older than the set lifetime is expired and returns
CONSENT.EXPIRED
. - Any consent returning EXPIRED before the set lifetime might be still valid. See consent error handling.
- Provide AIS data, e.g. IBANs, you were able to obtain from previous responses to the new session in the
consent_scope
.
Identifying accounts
The account ids (account.id
or account_id
) change irregularly. This makes them unsuitable for reliable identification of accounts, even though they give the impression that they could.
What is consistent and also always available from the banks is the IBAN or the account number and bank code/sort code/BIC.
Therefore we suggest following the logic to use the IBAN for account identification where it is available. If no IBAN is available, combine country code + bank code/sort code/BIC + account number as a unique identifier.
All you should do now is associate the accounts based on your identifier and then use the latest account ids when updating data.
You might ask why ids change. IBANs are considered personally identifiable information (PII) and are therefore not suitable for API requests as ids. IDs are not yet allowed to relate directly to the IBAN (which would make them PII as well), so they change.
Change of the transaction_id for already processed Transactions
There can be cases where an already processed transaction changes in its attributes, e.g. reference
or counter_party
. For example, a credit card transaction for a car rental is listed as processed but is only fully processed 2 weeks after it was first listed. This will likely result in a new transaction_id
.
If you update the transaction history and come across a new transaction_id
in a date range you previously already processed, then this can either be
- a newly processed transaction or
- an already processed transaction with a changed
transaction_id
.
Identify potential Duplicates (case 2)
The best way to distinguish between these two cases is to compare the apparently new transaction with already processed transactions on your side from the same day (transaction.date
).
Say you compare the new transaction (new
) with an existing transaction (existing
) from the same day based on the
- recipient (
counter_party.iban
), - amount (
amount.amount
), and - bank references (
bank_references.*
).
If new.recipient
equals existing.recipient
and new.amount
= existing.amount
but the transaction_id
is different the transactions might still be the same. The idea is that a transaction on the same date to the same recipient for the same amount is rather unlikely. You can further compare new.bank_references
with existing.bank_references
and search for a match amongst the 3 types of references (note: not all types are always available). If that is the case, you can almost certainly say that new
is an already existing transaction with a changed transaction_id
. We recommend transforming any reference into lowercase and removing white-spaces before comparing them.
Therefore you should replace or merge the existing transaction with the new transaction.
Why doesn't Klarna provide consistent transaction_ids
?
Banks do not always provide consistent ids for their transactions, so we try our best to compensate for that by generating a transaction_id
. But since we don't store transaction data, we can't compare them across requests, sessions or consents. The transaction_id
we provide is generated on-the-fly and primarily based on the transaction.reference
and therefore changes if the reference changes.