Working with PSD2 XS2A API
Introduction
3 banks / endpoints
Table of content
- 1 Introduction
- 1.1 Prerequisites
- 1.2 Embedded authentication
- 1.2.1 Create consent
- 1.2.2 Start authorisation
- 1.2.3 Choose SCA method
- 1.2.4 Finish SCA
- 1.3 Redirect approach
- 1.3.1 Verify consent
- 1.4 Decoupled approach
- 1.4.1 Create consent
- 1.4.2 Start authorisation
- 1.4.3 Choose decoupled method
- 1.4.4 Approve authorisation in Admin-Console
- 1.4.5 Verify SCA status
- 1.5 OAUTH 2.0 approach
- 1.5.1 Prerequisites
- 1.5.2 Get authorisation code
- 1.5.3 Get Access Token
- 1.6 Get Accounts
- 1.7 Get Transactions
Prerequisites
Create customer and fill SCA methods using Admin-Console (https://jrholding.atlassian.net/wiki/spaces/MPD/pages/679149583 ) or API (https://jrholding.atlassian.net/wiki/spaces/MPD/pages/685899802)
Embedded authentication
Create consent
Request example:
1
2
3
4
5
6
7
8
9
10
11
12
curl --location --request POST 'https://api.mockbank.io/v1/consents' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 3d1afce9-f7fe-4b3a-89cb-cd03b7820b63' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--data-raw '{
"access": {
"allPsd2": "allAccounts"
},
"frequencyPerDay": 0,
"recurringIndicator": false,
"validUntil": "2030-10-10"
}'
Response example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"consentStatus": "received",
"consentId": "{CREATED_CONSENT_ID}",
"_links": {
"self": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}"
},
"status": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/status"
},
"startAuthorisation": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations"
}
}
}
Start authorisation
Request example:
1
2
3
4
5
6
7
8
9
curl --location --request POST 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'X-Request-ID: e5b654ab-c95e-4014-be4f-1e043e714bca' \
--header 'Content-Type: application/json' \
--data-raw '{
"psuData": {
"password": "{YOUR_CUSTOMER_PASSWORD}"
}
}'
Response example:
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
{
"scaStatus": "psuAuthenticated",
"authorisationId": "{CREATED_AUTHORISATION_ID}",
"scaMethods": [
{
"authenticationType": "SMS",
"authenticationMethodId": "smstaniphonex",
"authenticationVersion": "0",
"name": "Verify by Phone",
"explanation": "Send SMS to +489********34",
"decoupled": false
},
{
"authenticationType": "APP",
"authenticationMethodId": "vaultappcheck",
"authenticationVersion": "0",
"name": "Verify by App",
"explanation": "Please check your app",
"decoupled": true
}
],
"_links": {
"updatePsuAuthentication": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
},
"scaStatus": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
}
}
}
Choose SCA method
Request example:
1
2
3
4
5
6
7
8
curl --location --request PUT 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'X-Request-ID: 652d39c2-f0e4-4d24-bf05-25bcc11e064a' \
--header 'Content-Type: application/json' \
--data-raw '
{
"authenticationMethodId": "smstaniphonex"
}'
Response example:
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
{
"scaMethods": [
{
"authenticationType": "SMS",
"authenticationMethodId": "smstaniphonex",
"authenticationVersion": "0",
"name": "Verify by Phone",
"explanation": "Send SMS to +489********34",
"decoupled": false
},
{
"authenticationType": "APP",
"authenticationMethodId": "vaultappcheck",
"authenticationVersion": "0",
"name": "Verify by App",
"explanation": "Please check your app",
"decoupled": true
}
],
"_links": {
"scaStatus": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
},
"authoriseTransaction": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
}
},
"scaStatus": "scaMethodSelected",
"authorisationId": "{CREATED_AUTHORISATION_ID}"
}
Finish SCA
Request example:
1
2
3
4
5
6
7
8
9
curl --location --request PUT 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'X-Request-ID: 59339c1d-f7f1-4112-bc18-8419a34c66f7' \
--header 'Content-Type: application/json' \
--data-raw '{
"scaAuthenticationData": "123321"
}'
Response example:
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
{
"scaMethods": [
{
"authenticationType": "SMS",
"authenticationMethodId": "smstaniphonex",
"authenticationVersion": "0",
"name": "Verify by Phone",
"explanation": "Send SMS to +489********34",
"decoupled": false
},
{
"authenticationType": "APP",
"authenticationMethodId": "vaultappcheck",
"authenticationVersion": "0",
"name": "Verify by App",
"explanation": "Please check your app",
"decoupled": true
}
],
"_links": {
"scaStatus": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
}
},
"scaStatus": "finalised",
"authorisationId": "{CREATED_AUTHORISATION_ID}"
}
Redirect approach
Create consent
Request example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl --location --request POST 'https://api.mockbank.io/v1/consents' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: b1c7e088-180c-49fc-8f45-889ad8b9381e' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'TPP-Redirect-Preferred: true' \
--header 'TPP-Redirect-URI: {YOUR_REDIRECT_URL_ON_SUCCESS}' \
--header 'TPP-Nok-Redirect-URI: {YOUR_REDIRECT_URL_ON_FAIL}' \
--data-raw '{
"access": {
"allPsd2": "allAccounts"
},
"frequencyPerDay": 0,
"recurringIndicator": false,
"validUntil": "2030-10-10"
}'
Response example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"consentStatus": "received",
"consentId": "{CREATED_CONSENT_ID}",
"_links": {
"scaRedirect": {
"href": "https://https://app.mockbank.io/sca/login?redirectId={REDIRECT_ID}&consentId={CREATED_CONSENT_ID}&internalRequestId={INTERNAL_REQUEST_ID}"
},
"self": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}"
},
"status": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/status"
}
}
}
Follow the “scaRedirect” link and use {YOUR_CUSTOMER_USERNAME}
and {YOUR_CUSTOMER_PASSWORD}
to log in:
Verify consent
Request example:
1
2
3
4
curl --location --request GET 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/status' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 860892f8-e91e-417e-8a7b-ca0ef9e1f7ee' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}'
Response example:
1
2
3
{
"consentStatus": "received"
}
Decoupled approach
It is similar to embedded approach. The only difference is when SCA method is being selected you need to use Admin-Console to approve or reject authorisation. No more authorisation updates required.
Create consent
1
2
3
4
5
6
7
8
9
10
11
12
curl --location --request POST 'https://api.mockbank.io/v1/consents' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 3d1afce9-f7fe-4b3a-89cb-cd03b7820b63' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--data-raw '{
"access": {
"allPsd2": "allAccounts"
},
"frequencyPerDay": 0,
"recurringIndicator": false,
"validUntil": "2030-10-10"
}'
Start authorisation
1
2
3
4
5
6
7
8
9
curl --location --request POST 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'X-Request-ID: e5b654ab-c95e-4014-be4f-1e043e714bca' \
--header 'Content-Type: application/json' \
--data-raw '{
"psuData": {
"password": "{YOUR_CUSTOMER_PASSWORD}"
}
}'
Choose decoupled method
1
2
3
4
5
6
7
8
9
{
"_links": {
"scaStatus": {
"href": "https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}"
}
},
"scaStatus": "scaMethodSelected",
"authorisationId": "{CREATED_AUTHORISATION_ID}"
}
Approve authorisation in Admin-Console
Verify SCA status
Request example:
1
2
3
curl --location --request GET 'https://api.mockbank.io/v1/consents/{CREATED_CONSENT_ID}/authorisations/{CREATED_AUTHORISATION_ID}' \
--header 'PSU-ID: {YOUR_CUSTOMER_USERNAME}' \
--header 'X-Request-ID: 6c4a8bef-4d5e-43e4-9889-3e01ae57158c'
Response example:
1
2
3
{
"scaStatus": "finalised"
}
OAUTH 2.0 approach
Prerequisites
Set up Client id, Client secret, Redirect urls for your organisation using Admin-Console
Example:
Get authorisation code
Go to link
1
https://oauth.mockbank.io/oauth/authorize?client_id={YOUR_CLIENT_ID}&response_type=code&redirect_uri={YOUR_REDIRECT_URL}
Authorise with {YOUR_CUSTOMER_USERNAME}
and {YOUR_CUSTOMER_PASSWORD}
Confirm existing scopes
After that you will receive redirect to {YOUR_REDIRECT_URL}?code={AUTHORISATION_CODE}
Get Access Token
Example request:
1
2
3
4
5
curl --location --request POST 'https://oauth.mockbank.io/oauth/token' \
--header 'Authorization: Basic {YOUR_CLIENTID_CLIENT_SECRET}' \
--form 'redirect_uri={YOUR_REDIRECT_URL}' \
--form 'code={AUTHORISATION_CODE}' \
--form 'grant_type=authorization_code'
Please note that YOUR_CLIENTID_CLIENT_SECRET
is effectively base64(clientid+":"+clientsecret)
Example response:
1
2
3
4
5
6
7
{
"access_token": "{ACCESS_TOKEN}",
"token_type": "bearer",
"refresh_token": "{REFRESH_TOKEN}",
"expires_in": 3649,
"scope": "balances accounts transactions"
}
Get Accounts
Request example using Consent-ID:
1
2
3
4
curl --location --request GET 'https://api.mockbank.io/v1/accounts' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 92b5abce-5aac-4187-b69e-8017a75bb21f' \
--header 'Consent-ID: {CREATED_CONSENT_ID}'
Request example using access token:
1
2
3
4
curl --location --request GET 'https://oauth-api.mockbank.io/v1/accounts' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 7db9a17e-b451-4126-afc7-6c78b49edb84' \
--header 'Authorization: Bearer {ACCESS_TOKEN}'
Response example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"accounts": [
{
"externalId": "{ACCOUNT_ID}",
"resourceId": "fe1184f6-4b04-4887-b227-1e3b78e827fe",
"iban": "DE89370400440532013002",
"bban": "370400440532013001",
"pan": "120000003",
"maskedPan": "12******3",
"currency": "EUR",
"name": "Current",
"cashAccountType": "CASH",
"accountStatus": "ENABLED",
"bic": "MOCKDEXXXXX",
"ownerName": "AlexforDel"
}
]
}
Get Transactions
Request example using Consent-ID
1
2
3
4
curl --location --request GET 'https://api.mockbank.io/v1/accounts/{ACCOUNT_ID}/transactions?bookingStatus=both' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 1ee4bd47-2f34-4a4e-9fc9-853166da2194' \
--header 'Consent-ID: {CREATED_CONSENT_ID}'
Request example using access token:
1
2
3
4
curl --location --request GET 'https://oauth-api.mockbank.io/v1/accounts/{ACCOUNT_ID}/transactions?bookingStatus=both' \
--header 'Content-Type: application/json' \
--header 'X-Request-ID: 7db9a17e-b451-4126-afc7-6c78b49edb84' \
--header 'Authorization: Bearer {ACCESS_TOKEN}'
Response example:
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
{
"account": {
"iban": "DE89370400440532013002",
"bban": "370400440532013001",
"pan": "120000003",
"maskedPan": "12******3",
"currency": "EUR"
},
"transactions": {
"booked": [
{
"transactionId": "5dffbe98-2263-40de-b4a6-36a1a3e27d6a",
"entryReference": "ref-xxx",
"endToEndId": "id-xxx",
"checkId": "check-xxx",
"creditorId": "creditorId",
"bookingDate": "2020-01-26",
"valueDate": "2020-01-25",
"creditorName": "creditorName",
"creditorAccount": {
"iban": "iban",
"bban": "bban",
"pan": "pan",
"maskedPan": "maskedPan",
"msisdn": "msisdn",
"currency": "EUR"
},
"ultimateCreditor": "ultimateCreditor",
"debtorName": "debtorName",
"debtorAccount": {
"iban": "iban",
"bban": "bban",
"pan": "pan",
"maskedPan": "maskedPan",
"msisdn": "msisdn",
"currency": "EUR"
},
"ultimateDebtor": "ultimateDebtor",
"remittanceInformationUnstructured": "remittanceInformationUnstructured",
"remittanceInformationStructured": "remittanceInformationStructured",
"additionalInformation": "additionalInformation",
"purposeCode": "BKDF",
"proprietaryBankTransactionCode": "proprietaryBankTransactionCode",
"transactionAmount": {
"currency": "EUR",
"amount": -434.00
},
"bankTransactionCode": "bankTransactionCode"
}
]
}
}