Technical documentation

Notes

In this document the IBAN and BIC codes are intentionally replaced with technically invalid placeholders. The PSD2 implementation will return valid values.

If this document conflicts with the Berlin Group Implementation Guideline v1.3, the Berlin Group Implementation Guideline v1.3 should be followed, unless otherwise specified.

Consents

Create Consent

POST /v1/consents

The following JSON document creates a consent request for account and account balance information access. The accounts to which the PSU eventually grants access is negotiated between the PSU and the ASPSP. The status of the account access negotiation can be obtained with "Get Consent Status" and the full consent information with "Get Consent".

While the Berlin Group API knows access qualifiers "allPsd2" and "allAccounts", those can not be used in the Samlink PSD2 API implementation. The account access is always negotiated between the PSU and the ASPSP. If the "validUntil" date is further than 90 days in the future, the PSD2 implementation will adjust it to 90 days. Therefore it is ok to use date 9999-01-01 for consents of maximum duration. Likewise if the "frequencyPerDay" value is greater than 4 it will be adjusted to 4. If "recurringIndicator" is "false" the "frequencyPerDay" must be "1".

The following request creates a recurring consent with maximum validity period for account information and balance information for unspecified acounts. The accounts to which the consent is granted are filled in if the PSU confirms the consent.

{
"access": {
"accounts": [],
"balances": []
},
"combinedServiceIndicator": false,
"frequencyPerDay": 4,
"recurringIndicator": true,
"validUntil": "9999-01-01"
}

The response will contain the consent status, ID and links to the authentication service in which the account access negotiation between the PSU and the ASPSP will take place.

{
"consentStatus": "received",
"consentId": "a2753a17-b39d-4bfc-8ffd-44a04a735bf2",
"_links": {
"scaOAuth": "https://example.com/auth/",
"self": "/psd2/v1/consents/a2753a17-b39d-4bfc-8ffd-44a04a735bf2",
"status": "/psd2/v1/consents/a2753a17-b39d-4bfc-8ffd-44a04a735bf2/status"
}
}

Note: Calling Get Consent Status or Get Consent before the PSU has returned from the OAuth2 flow causes the consent to be cached, which adds a delay before changes to the consent become visible to the TPP.

Get Consent Status

GET /v1/consents/{consentId}/status

Get Consent Status does not contain a request body. The response will only contain the current status of the consent.

{
"consentStatus": "received"
}

Get Consent

GET /v1/consents/{consentId}

Get Consent does not contain a request body. The response will contain complete consent information.

{
"access": {
"accounts": [ {
"iban": "FI0000000000000000",
"resourceId": "e8f816f3-14d3-42a2-a440-f41613f16255"
}, {
"iban": "FI0000000000000001",
"resourceId": "addac7ad-6c5e-40c0-a7ae-2787ce3faf38"
} ],
"balances": [ {
"iban": "FI0000000000000000",
"resourceId": "e8f816f3-14d3-42a2-a440-f41613f16255"
}, {
"iban": "FI0000000000000001",
"resourceId": "addac7ad-6c5e-40c0-a7ae-2787ce3faf38"
} ]
},
"recurringIndicator": true,
"validUntil": "2019-03-19",
"frequencyPerDay": 4,
"lastActionDate": "2018-12-19",
"consentStatus": "valid"
}

Delete Consent

DELETE /v1/consents/{consentId}

Delete Consent does not contain a request or respose body. HTTP response status code 200 is returned if the consent is successfully deleted. It's status will be "terminatedByTpp" and it can no longer be used to access account information. The consent can be accessed via Get Consent and Get Consent Status until maintenance operations remove it from the database.

Accounts

Account operations are governed by the daily consent use restrictions. When the PSU is actively using the TPP service, the IP address from which the PSU accesses the TPP service shall be included in the PSU-IP-Address header. This information is used to determine whether the daily consent use restrictions are applied or not. When the PSU is not actively using the TPP service, the TPP is restricted to no more than 4 requests per day (unless a lower frequencyPerDay value was specified during the consent creation).

PSU-IP-Address: 172.217.21.163

List Accounts

GET /v1/accounts

List Accounts does not contain a request body. The response will contain basic account information for all accounts allowed by the consent specified in the Consent-ID header. The example shows accounts in a consent that grants access to basic account informations and account balance information. Had the consent also been granted to transaction information, the _links section would contain a link to the transactions-endpoint.

The "withBalance" URL parameter is not supported.

{
"accounts": [ {
"resourceId": "e8f816f3-14d3-42a2-a440-f41613f16255",
"iban": "FI0000000000000000",
"currency": "EUR",
"name": "CURRENT ACCOUNT",
"cashAccountType": "CASH",
"status": "enabled",
"bic": "ABCDEFGH",
"_links": {
"balances": "/v1/accounts/e8f816f3-14d3-42a2-a440-f41613f16255/balances",
}
}, {
"resourceId": "addac7ad-6c5e-40c0-a7ae-2787ce3faf38",
"iban": "FI0000000000000001",
"currency": "EUR",
"name": "MY SAVINGS ACCOUNT",
"cashAccountType": "CASH",
"status": "enabled",
"bic": "ABCDEFGH",
"_links": {
"balances": "/v1/accounts/addac7ad-6c5e-40c0-a7ae-2787ce3faf38/balances",
}
} ]
}

The fields returned from list accounts are:

  • resourceId: Identifier of the account in PSD2 AIS API
  • iban: Account number in IBAN format
  • currency: Account currency
  • name: Name given to account by PSU
  • cashAccountType: Account type
  • status: Account status
  • bic: BIC associated to the account
  • _links/balances: Link to account balance (if balance premission was granted in the consent)
  • _links/transactions: Link to account transactions (if transaction premission was granted in the consent)

Read Account Details

GET /v1/accounts/{resourceId}

Read Accounts Details does not contain a request body. The response will contain account information for the account specified in the URL path. The resource ID of the account must be of one of the accounts in the consent specified in the Consent-ID header.

{
"resourceId": "7bf3a0f4-db88-4d4d-9d23-8a59c2724b4f",
"iban": "FI0000000000000003",
"currency": "EUR",
"cashAccountType": "CASH",
"status": "enabled",
"bic": "ABCDEFGH",
"_links": {
"balances": "/v1/accounts/7bf3a0f4-db88-4d4d-9d23-8a59c2724b4f/balances",
"transactions": "/v1/accounts/7bf3a0f4-db88-4d4d-9d23-8a59c2724b4f/transactions"
}
}

The fields returned from read accounts details are:

  • resourceId: Identifier of the account in PSD2 AIS API
  • iban: Account number in IBAN format
  • currency: Account currency
  • product: Product name of account
  • cashAccountType: Account type
  • status: Account status
  • bic: BIC associated to the account
  • _links/balances: Link to account balance (if balance premission was granted in the consent)
  • _links/transactions: Link to account transactions (if transaction premission was granted in the consent)

Read Balance

GET /v1/accounts/{resourceId}/balances

Read Balance does not contain a request body. The response will contain balance information for the account specified in the URL path. The resource ID of the account must be of one of the accounts in the consent specified in the Consent-ID header and the consent must grant access to balances for the specified account.

{
"account": {
"iban": "FI0000000000000003"
},
"balances": [ {
"balanceAmount": {
"currency": "EUR",
"amount": "48115.40"
},
"balanceType": "forwardAvailable",
"lastChangeDateTime": "2018-12-05T00:00:00Z",
"referenceDate": "2018-12-05"
} ]
}

The fields returned from read balance are:

  • account/iban: Account number in IBAN format
  • balances/balanceAmount/currency: Account currency
  • balances/balanceAmount/amount: Account balance amount
  • balances/balanceType: Always "forardAvailable"
  • balances/referenceDate: Reference date of the balance

Read Transaction List

GET /v1/accounts/{resourceId}/transactions/?bookingStatus={bookingStatus}

Read Transaction List does not contain a request body. The response will contain transactions for the account specified in the URL path. The resource ID of the account must be of one of the accounts in the consent specified in the Consent-ID header and the consent must grant access to transactions for the specified account. Booked transactions are retrieved with bookingStatus parameter "booked". Pending transactions are retrieved with bookingStatus parameter "pending". The bookingStatus parameter "both" is not supported.

For booked transactions, if no other URL parameters are specified, the response contains 10 latest transactions. To get next 10 transactions the entryReference of the last transaction in the list shall be given in the entryReferenceFrom parameter. To get all transactions between a date interval, both dateFrom and dateTo must be given. The entryReferenceFrom parameter can not be used with the date interval parameters. The pending transaction listing does not support paging or date interval searching. All pending transactions are always returned in one response.

A sample response for booked transaction query with no search parameters (the list is truncated to two transactions for brevity):

{
"account": {
"iban": "FI0000000000000003"
},
"transactions": {
"booked": [
{
"entryReference": "000000000001017",
"bookingDate": "2018-12-05",
"transactionAmount": {
"currency": "EUR",
"amount": "-50.00"
},
"creditorName": "JANE DOE"
}, {
"entryReference": "000000000001016",
"bookingDate": "2018-11-14",
"transactionAmount": {
"currency": "EUR",
"amount": "5.59"
},
"debtorName": "JOHN DOE"
"_links": {
"account": "/psd2/v1/accounts/7bf3a0f4-db88-4d4d-9d23-8a59c2724b4f"
}
}
}

A sample response for pending transaction query:

{
"account": {
"iban": "FI0000000000000003"
},
"transactions": {
"pending": [
{
"valueDate": "2018-09-10",
"transactionAmount": {
"currency": "EUR",
"amount": "50.00"
},
"creditorName": "JOHN DOE",
"debtorAccount": {
"iban": "FI0000000000000003"
}
}, {
"valueDate": "2038-12-22",
"transactionAmount": {
"currency": "EUR",
"amount": "1.00"
},
"creditorName": "JANE DOE",
"creditorAccount": {
"iban": "SE0000000000000001"
},
"debtorAccount": {
"iban": "FI0000000000000003"
}
}
]
}
}

Payments

Payment information and payment status request endpoints are shared by single and periodic payments. The payment-product URL path component defines whether the payment in question is a single payment (payments) or a periodic payment (periodic-payments).

Payment Initiation Request (Single SEPA payment)

POST /v1/payments/sepa-credit-transfers

The following JSON document contains the minimum set of fields for creating a SEPA payment initiation request. While the creditorAccount object allows both "iban" and "bban" fields and the creditorAgent allows both IBAN and clearing code formats, SEPA payments can only be made with an IBAN and a BIC.

Either the endToEndIdentification or remittanceInformationUnstructured must be provided. The endToEndIdentification will be used as the payment reference number and it can be either a domestic 20-digit reference number or a 25-character Creditor Reference. The remittanceInformationUnstructured will be used as the payment message.

The creditorAgent fields is optional.

{
"creditorAccount": {
"iban": "FI0000000000000004"
},
"creditorAgent": "ABCDEFGH",
"creditorName": "JANE DOE",
"debtorAccount": {
"iban": FI0000000000000003"
},
"instructedAmount": {
"amount": 50.0,
"currency": "EUR"
},
"remittanceInformationUnstructured": "PAYMENT TO JANE",
"endToEndIdentification": "12345 67890 12345 67904"
}

A sample response for payment initiation.

{
"transactionStatus": "RCVD",
"paymentId": "b3763c20-6e99-4e3d-9af6-6443eccb6c79",
"transactionFeeIndicator": false,
"_links": {
"scaOAuth": "https://example.com/auth/",
"self": "/psd2/v1/payments/sepa-credit-transfers",
"status": "/psd2/v1/payments/b3763c20-6e99-4e3d-9af6-6443eccb6c79/status"
}
}

Payment Initiation Request (Single foreign payment)

POST /v1/payments/cross-border-credit-transfers

The following JSON document contains the fields for creating a foreign payment initiation request. The "creditorAccount" can be specified with either an "iban" or "bban" field and the "creditorAgent" value can be either a BIC or a clearing code.

The "creditorAddress" field must contain "country" and at least one other field.

{
"creditorAccount": {
"bban": "1234567890123456"
},
"creditorAgent": "FW123456789",
"creditorName": "JANE DOE",
"creditorAddress": {
"street": "Street Name",
"buildingNumber": "10",
"city": "City Name",
"postalCode": "12345",
"country": "US"
},
"debtorAccount": {
"iban": "FI0000000000000003"
},
"instructedAmount": {
"amount": 50.00,
"currency": "USD"
},
"remittanceInformationUnstructured": "PAYMENT TO JANE"
}

The response is identical to that of single SEPA payment initiation, except for the _links-section, which points to the corresponding payment-service and payment-product.

Payment Initiation Request (Periodic)

POST /v1/periodic-payments/sepa-credit-transfers

The following JSON document contains the fields for creating a periodic payment initiation request on the fifth day of each month starting on 2019-03-05 and ending on 2019-12-31. While the creditorAccount object allows both "iban" and "bban" fields and the creditorAgent allows both IBAN and clearing code formats, periodic payments can only be made as SEPA payments, thus the fields can only contain an IBAN and a BIC and the same restrictions on endToEndIdentification and remittanceInformationUnstructured apply.

{
"creditorAccount": {
"iban": "FI0000000000000004"
},
"creditorAgent": "ABCDEFGH",
"creditorName": "JANE DOE",
"debtorAccount": {
"iban": "FI0000000000000003"
},
"remittanceInformationUnstructured": "MONTHLY PAYMENT TO JANE",
"startDate": "2019-03-05",
"endDate": "2019-12-31",
"frequency": "Monthly",
"instructedAmount": {
"amount": 50.0,
"currency": "EUR"
}
}

The executionRule and dayOfExecution fields can only be used when creating a periodic payment on last bank day of month. The fields must then have values "preceeding" and "31" and the frequency must be "Monthly" (i.e. on the last day of the month, but before any bank holidays):

{
"creditorAccount": {
"iban": "FI0000000000000004"
},
"creditorAgent": "ABCDEFGH",
"creditorName": "JANE DOE",
"debtorAccount": {
"iban": "FI0000000000000003"
},
"remittanceInformationUnstructured": "LAST BANK DAY OF MONTH PAYMENT",
"startDate": "2019-03-30",
"endDate": "2019-12-31",
"frequency": "Monthly",
"executionRule": "preceeding",
"dayOfExecution": "31",
"instructedAmount": {
"amount": 50.0,
"currency": "EUR"
}
}

The response is identical to that of single SEPA payment initiation, except for the _links-section, which points to the corresponding payment-service and payment-product.

Get Payment Information

GET /v1/{payment-service}/{payment-product}/{paymentId}

Get payment information request does not contain a request body. The response will contain information of a specific payment identified by the payment ID.

A sample response for payment information.

{
"endToEndIdentification": null,
"debtorAccount": {
"iban": "FI0000000000000003"
},
"instructedAmount": {
"currency": "USD",
"amount": "50.00"
},
"creditorAccount": {
"bban": "471900-15514"
},
"creditorAgent": "FW123456789",
"creditorName": "JANE DOE",
"creditorAddress": {
"street": "Street Name",
"buildingNumber": "10",
"city": "City Name",
"postalCode": "12345",
"country": "US"
},
"remittanceInformationUnstructured": "PAYMENT TO JANE",
"transactionStatus": "RCVD"
}

Payment Initiation Status Request

GET /v1/{payment-service}/{payment-product}/{paymentId}/status

Payment initiation status request does not contain a request body.

The response is simply the status of the payment:

{
"transactionStatus": "RCVD"
}

Supported payments statuses are

  • RCVD: Payment initiation request has been received and passed initial technical checks.
  • ACTC: Payment has been accepted by PSU and passed initial technical checks.
  • PDNG: Payment pending (applies only to cross border payments).
  • ACSC: Payment has been processed. The final state of single SEPA payments and cross border payments.
  • ACSP: Payment has been processed. The final state of periodic SEPA payments.
  • RJCT: Payment processing failed.
  • CANC: Payment has been cancelled (applies only to periodic SEPA payments).

Payment Cancellation Request

DELETE /v1/periodic-payments/sepa-credit-transfers/{paymentId}

Payment cancellations can only be performed on periodic SEPA credit transfers. A successful cancellation will cancel all subsequent payments of the periodic payment instance that have not been sent to payment service for processing. Payment Cancellation Request does not contain a request body. The response will contain an HTTP status code 200 and the status of the payment (CANC). If a periodic payment can not be cancelled, HTTP status code 405 is returned.

A sample response for payment cancellation request:

{
"transactionStatus": "CANC"
}

Confirmation Of Funds

Confirmation Of Funds Request

POST /v1/funds-confirmations

The following request performs a confirmation of funds request for 40.00EUR to a specified account. While the account object allows "iban", "bban", "currency", "maskedPan", "msisdn" and "pan" fields , confirmation of funds requests can only be made with an IBAN. All other fields in the account object, as well as the "cardNumber" and "payee" fields, are ignored.

{
"account": {
"iban": "FI0000000000000003"
},
"instructedAmount": {
"amount": 40.00,
"currency": "EUR"
}
}

The response only tells whether or not the account has funds for the requested amount.

{
"fundsAvailable": true
}

TPP Registration API

TPP registration API is not a part of the Berlin Group PSD2 API specification.

Signing

All messages sent to TPP registration API must be signed using a valid QSEAL certificate. Message signing is performed in similar manner with the Samlink PSD2 API. Specification for the HTTP message signing can be found in Berlin Group Implementation Guideline v1.3 (chapter 12) with the following restrictions.

Mandatory headers are

  • Digest: SHA-256 or SHA-512 digest of the message content, as specified by Berlin Group Implementation Guideline.
  • X-Request-ID: UUID, as specified by Berlin Group Implementation Guideline.
  • TPP-Redirect-URI: only in TPP registration, as specified by Berlin Group Implementation Guideline.
  • TPP-Signature-Certificate: TPP's eIDAS QSEAL certificate, as specified by Berlin Group Implementation Guideline.
  • Signature: as specified by Berlin Group Implementation Guideline (chapter 12.2), constructed from headers Digest, X-Request-ID and TPP-Redirect-URI.

TPP-Redirect-URI is recorded during TPP registration. Subsequent calls to Samlink PSD2 API, where the TPP-Redirect-URI header is required, must match the recorded value (see Berlin Group Implementation Guideline).

Encryption

All communication between the client and the TPP registration API must be encrypted using TLS.

TPP Registration Request

PUT /tpp-registration/v1/tpp/{TPP-Global-URN}?ForceNewApiKey={boolean}

The following JSON document, along with the aforementioned HTTP headers, registers the short name and OAuth2 redirect URI of an AIS and/or PIS, identified by the TPP-Global-URN parameter, to Samlink PSD2 API. Short name is the name that is shown to the PSU during during payment and consent confirmation. It's maximum length is 35 characters and it is mandatory.

{
"shortName": "Royal Bank Of Scotland"
}

A registration request can be sent multiple times. A new API key will be registered on the first request or if the ForceNewApiKey query parameter is true. The currently registered API key is returned in the success-response.

The response to the successful registration contains the API key that AIS and/or PIS uses to gain access to the Samlink PSD2 API.

{
"success": "true",
"message": "OK",
"apiKey": "c144bf8e-4c9a-4095-95db-efeef823f450",
"newApiKeyCreated": "true"
}

If the newApiKeyCreated parameter is "false" the value returned in apiKey is the key that was generated in the last successful registration request.

Errors are returned with the same data structure as the success response. HTTP status code is either 400 or 500, the "success" parameter is "false" and the "message" parameter contains a human readable error message.

{
"success": "false",
"message": "TPP certificate encoding error"
}

Example

PUT /tpp-registration/v1/tpp/FI-ABC-123456 HTTP/1.1
Host: psd2.example.com
Date: Thu, 6 Jun 2019 11:22:31 GMT
X-Request-ID: 6ad53b20-c4d8-4b5a-b2d8-fe29a3a24519
Digest: SHA-256=rCC59Xpw9DdFCB+VUT2yzGWgkZfJJoo1NJv4mQQxv0w
TPP-Signature-Certificate: [TPP's eIDAS certificate]
TPP-Redirect-URI: https://example.com/oauth/redirect
Signature: keyId="SN=00f3abe28bee1e8f10,CA=OID.2.5.4.97=PSDFI-ABC-123456,C=FI,O=Samlink,CN=PSD2",algorithm="rsa-sha256", \
headers="Digest X-Request-ID TPP-Redirect-URI", \
signature="Base64(RSA-SHA256(signing string))"
Content-Type: application/json

{
"shortName": "Royal Bank Of Scotland"
}

Certificate Registration Request

POST /tpp-registration/v1/certificate

Certificates are registered in a separate step after TPP registration. The certificate registration request does not contain a body. All information required in the request is contained in the HTTP request signature.

Example

POST /tpp-registration/v1/certificate HTTP/1.1
Host: psd2.example.com
Date: Thu, 6 Jun 2019 11:22:31 GMT
X-Request-ID: 6ad53b20-c4d8-4b5a-b2d8-fe29a3a24519
Digest: SHA-256=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU
TPP-Signature-Certificate: [TPP's eIDAS certificate]
Signature: keyId="SN=00f3abe28bee1e8f10,CA=OID.2.5.4.97=PSDFI-ABC-123456,C=FI,O=Samlink,CN=PSD2",algorithm="rsa-sha256", \
headers="Digest X-Request-ID", \
signature="Base64(RSA-SHA256(signing string))"
Content-Length: 0

List Certificates Request

GET /tpp-registration/v1/certificate

Returns list of all certificates registered by the TPP. The list certificate request does not contain a body. All information required in the request is contained in the HTTP request signature. The response contains the certificate identifier within the TPP registration service, certificate serial number and status.

{
"certificates": [
{
"certificateId": "7c990b13-e9ec-4a89-9543-c046a231618f",
"serialNumber": "1234567890",
"status": "revoked"
}
],
"message": "OK",
"success": true
}

Delete Certificate Request

DELETE /tpp-registration/v1/certificate/{CertificateId}

Deletes a certificate. The certificate is identified by the certificateId, which is returned in the list certificates response. The delete certificate request does not contain a body. All information required in the request is contained in the HTTP request signature. The response contains the result as in TPP registration.

{
"success": "true",
"message": "OK"
}

Example

DELETE /tpp-registration/v1/certificate/7c990b13-e9ec-4a89-9543-c046a231618f HTTP/1.1
Host: psd2.example.com
Date: Thu, 6 Jun 2019 11:22:31 GMT
X-Request-ID: 6ad53b20-c4d8-4b5a-b2d8-fe29a3a24519
Digest: SHA-256=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU
TPP-Signature-Certificate: [TPP's eIDAS certificate]
Signature: keyId="SN=00f3abe28bee1e8f10,CA=OID.2.5.4.97=PSDFI-ABC-123456,C=FI,O=Samlink,CN=PSD2",algorithm="rsa-sha256", \
headers="Digest X-Request-ID", \
signature="Base64(RSA-SHA256(signing string))"
Content-Length: 0