PSD2

This page contains the details of PSD2 and the API endpoints to work available.

What is PSD2

PSD2 stands for Second Payment Services Directive, and itโ€™s EU (European Union) wide directive that dictates that you (the end-user) own your account data, not your bank.

With PSD2, all institutions with a banking license have a duty to ensure that they provide secure, regulated and free access to open banking APIs through which end users have a right to make their data accessible to other service providers. This information movement is carried out by licensed Third Party Providers (TPP's) by integrating directly with open banking APIs and allowing companies to use these connections in their applications/platforms, where end users can benefit from this functionality.

What data can we get with PSD2?

PSD2 is all about payments and payment account data. Consequently, the information you can get is limited to payment accounts - checking accounts, current accounts and credit cards. Savings accounts, investment accounts or similar wouldnโ€™t be shown. A general rule of thumb is - if you can make and receive payments from the mentioned accounts, you should be able to access this data via PSD2 APIs.

Nordigen also maintains a data points google sheet which lists all banks tested in production and the respective data points they return for each endpoint. This sheet is updated every week.

General Overview of the Data Points

  • Account details: holder name, a list of account holder's accounts and IBAN.

  • Account balance: current and available.

  • Transaction data: date, merchant or counter-party (partner) name, description (info field), transaction amount.

    • Up to 2 years of history (730 days) and up to 90 days of continuous access to linked accounts.

What is continuous Access, and why the 90 days limit

The Regulatory Technical Standards state that banking institutions must ensure that Third Party Providers (TPPs) can access linked accounts 90 days post-authentication without asking the end user to re-authenticate. This is critical for various applications and uses cases that rely on being able to pool in new transactions as they happen, for example, budgeting apps and accounting platforms.

Access to linked accounts is valid for 90 days only because there is a requirement to apply strong customer authentication by Article 10 of Regulatory Technical Standards (read more about it here). This time frame applies to all PSD2 APIs and all Third Party Providers that connect to these APIs.

Workflow

Pre-requirements: The users need an account with KYC verification to use the endpoints.

Steps for authorising a bank account with PSD2

Get Available Countries

To get the available countries, make a GET request using the below endpoint.

The response will contain a list of countries in short form. A sample response is given below:

[
    "NO",
    "SE",
    "FI",
    "DK",
    "EE",
    "LV",
    "LT",
    "GB",
    "NL",
    "CZ",
    "ES",
    "PL",
    "BE",
    "DE",
    "AT",
    "BG",
    "HR",
    "CY",
    "FR",
    "GR",
    "HU",
    "IS",
    "IE",
    "IT",
    "LI",
    "LU",
    "MT",
    "PT",
    "RO",
    "SK",
    "SI"
]

Get Institutions

To get the institutes under a country, make a request using the country short form as the query value.

Pass the country value as a query from the previous request's response to get the available institutions under that country. For example: if you want to get all the institutes in Germany, then pass "GR" as the query value of "country". The final endpoint should look like the below:

baseUrl/v1/psd2/nordigen/institutions?country=GR

This request returns a list of objects that contains id, name, bic, transactionTotalDays, countries, logo and payment object. A sample response is given below:

[
    {
        "id": "SANDBOXFINANCE_SFIN0000",
        "name": "Sandbox Finance",
        "bic": "SFIN0000",
        "transactionTotalDays": "90",
        "countries": [
            "XX"
        ],
        "logo": "https://cdn.nordigen.com/ais/SANDBOXFINANCE_SFIN0000.png",
        "payments": null
    }
]

Keep in mind that you will need the id in the subsequent request.

Bank Account Access

After getting the list of institutions, select one institution and use the id of that institution. You have to make a requisition request to access the bank account.

Create Requisition

Pass the institution Id in the body of the request to identify the institution that you are referring to:

{
        "institutionId" : "SANDBOXFINANCE_SFIN0000"
}

The response contains a link that can be used to navigate the user to. After visiting the link, depending on the institution, the user will see what kind of data the user will share by providing access to the account. The user will have to agree to the terms and conditions. After agreeing, the user will be navigated to the login or auth page, where the user will enter the bank account credentials. After successful login, they will be navigated to the success or failure page.

Getting Accounts

After making a requisition, you can get the accounts from that institution. This request provides basic information such as the name, balance, iban, etc. You can also get the specific account details by making a GET request to /accounts/{id}/details endpoint given below.

The response contains a list of objects having basic account details. A sample response to the request is given below:

[
    {
        "id": "5983e5de-f6c0-442e-861c-54cc1314a38b",
        "name": "Sandbox Finance",
        "logo": "https://cdn.nordigen.com/ais/SANDBOXFINANCE_SFIN0000.png",
        "balances": [
            {
                "amount": "3.00",
                "currency": "EUR",
                "balanceType": "interimAvailable"
            }
        ],
        "requisitionId": "27b702d3-04b9-4b8a-80ce-4150029857c6",
        "requisitionStatus": "EX",
        "institutionId": "SANDBOXFINANCE_SFIN0000",
        "iban": "XXXXXXXXXXXXXX",
        "accountStatus": "EXPIRED"
    }
]

Explanation of the Requisition Status

A requisition acquires an account and can be of different statuses. To understand better, please follow the table:

Status shortStatus longDescriptionStage*

CR

CREATED

Requisition has been successfully created

1

GC

GIVING_CONSENT

End-user is giving consent at Nordigen's consent screen

2

UA

UNDERGOING_AUTHENTICATION

End-user is redirected to the financial institution for authentication

3

RJ

REJECTED

Either SSN verification has failed or end-user has entered incorrect credentials

4

SA

SELECTING_ACCOUNTS

End-user is selecting accounts

5

GA

GRANTING_ACCESS

End-user is granting access to their account information

6

LN

LINKED

Account has been successfully linked to requisition

7

SU

SUSPENDED

Requisition is suspended due to numerous consecutive errors that happened while accessing its accounts

8

EX

EXPIRED

Access to accounts has expired as set in End User Agreement

9

*describes the sequence for each possible status, where โ€œ1โ€ is starting status.

Explanation of the Account Status

The previous request contains an object accountStatus which provides the account's status as the word says. This status can be of different types. Follow the table given below to understand it better:

Status LogDescription

DISCOVERED

The user has successfully authenticated herself, and the account has been discovered.

ERROR

An error was encountered when processing account.

EXPIRED

Access to account has expired as set in End User Agreement.

PROCESSING

Account is being processed by the institution.

READY

Account has been successfully processed.

SUSPENDED

The account has been suspended (more than 10 consecutive failed attempts to access the account).

Delete a Requisition

After acquiring a requisition, you can also delete or remove it. To delete a requisition, you have to have the requisition id. You can get the requisition id from the previous request. When an account is expired, you can see the account status in the previous request. If it is "EXPIRED" you will have to remove it because you can't work with that account anymore, and you will have to make a requisition again.

Make a DELETE request using the following endpoint to remove it:

Account Transaction List

To get the detailed transaction record of an account, make a GET request to the following endpoint with the account id:

Here the id is the account id, NOT the requisition id.

The response returns a list of objects containing that account's transaction details. The details contain the account of the creditor, booking date, transaction amount details (amount and currency), creditor name, and proprietary Bank Transaction Code to understand what type of transaction it was. The response contains two types of transactions:

  1. Booked

  2. Pending

A sample response is given below:

[
    "booked": [
        {
            "creditorAccount": {
                "iban": "XXXXXXXXXXXXXXXXX"
            },
            "bookingDate": "2022-12-19",
            "transactionAmount": {
                "amount": "-7.89",
                "currency": "EUR"
            },
            "remittanceInformationUnstructured": "SAMPLE 1234 BERLIN DE",
            "creditorName": "SAMPLE John",
            "proprietaryBankTransactionCode": "CARD_TRANSACTION"
        }, 
        {
            "creditorAccount": {
                "iban": "XXXXXXXXXXXXXXXXX"
            },
            "bookingDate": "2022-11-18",
            "transactionAmount": {
                "amount": "-2.48",
                "currency": "EUR"
            },
            "remittanceInformationUnstructured": "SAMPLE 1234 BERLIN DE",
            "creditorName": "SAMPLE Doe",
            "proprietaryBankTransactionCode": "CARD_TRANSACTION"
        },
    ], 
    "pending": []
]

Account Details

To get the account details of an account, such as the currency, iban, and resource id, make a GET request to the following endpoint:

Here the id is the account id, NOT the requisition id.

Account Balance

To get the balance of an account, make a GET request to the following endpoint:

A sample response is given below:

{
    "balances": [
        {
            "balanceAmount": {
                "amount": "0.78",
                "currency": "EUR"
            },
            "balanceType": "interimAvailable",
            "referenceDate": "2023-01-01"
        }
    ]
}

Last updated