# PSD2 Sandbox Documentation

Dear developer

Within this section you can find additional documentation regarding the operation of the sandbox. The information will be updated and completed as a reaction of questions and need of clarifications by developer on a regular basis.

Table of Contents

# API Documentation

The complete documentation of the API can be found here (opens new window). It is a swagger ui which describes the API and the data model and which can also be used to test and execute the sandbox API manually.

# Differences between the sandbox and the productive API

The API and the data model of the sandbox is basically identical to the real API. However, there are a few small differences which are worth mentioning here. These are mainly

  • TPP client authentication
  • User interaction
  • State changes

# TPP client authentication

The real API uses client certificates to authenticate the TPP client whereas the sandbox only uses basic authentication. Hence, it is not necessary to use a client certificate when accessing the sandbox api, just send the basic authentication credentials within your request or use the session cookie which you received from the previous request. All roles (PISP,AISP and PIISP) will be assigned to the TPP by default.

# User interaction

The real API returns a URL which must be used to redirect the user to the login page. There, he can authenticate himself and execute the payment or accept the consent. However, in the sandbox we don't have an interactive user and hence, the API will not return a URL for redirection.

# State changes

In the real word, the transaction status of a payment order will change in time. It will start with the status RCVD (Received) and might hopefully end with ACSC (AcceptedSettlementCompleted). However, in the sandbox, there is no background process which changes the status of an object. The sandbox simply sets the status of the object during its creation time as a function of the X-Request-ID. See the chapter "Encoding" for details.

# Encoding

The last digit of the X-Request-ID HTTP-Header (e.g. for 99391c7e-ad88-49ec-a2ad-99ddcb1f7721 this would be 1) contains the encoding which determines the status of the created object in the sandbox. The mapping is defined as follows:

# CreatePayment

1: RCVD
2: RJCT
3: CANC
4: PNDG
5: ACSC

Default: ACSC

# ConsentCreation

0: received
1: valid
2: rejected
3: revokedByPsu
4: expired
5: terminatedByTpp

Default: valid

# Getting started with curl

This chapter contains some example API calls to give you a quick start. The examples use the curl command, which is available on all unix based operating systems. For Windows-Users, we recommend the usage of mobaXTerm which contains a pretty good implementation of curl. Git Bash also contains a curl command, but this implementation might lead to problems when using non-Ascii text in the body (e.g. german Umlaute in names and Addresses). We don't recommend the usage of the curl command which comes with the cmd.exe, it has some major issues which lead to errors.

Let's jump right in and create a payment order.

# Create a payment order

Use the following command to create a payment order:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/payments/cross-border-credit-transfers \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "TPP-Redirect-URI: https://www.google.ch" \
--header "PSU-IP-Address: 192.0.0.12" \
--header "Content-Type: application/json" \
--data '{"debtorAccount":{"iban":"LI3808805500000000012"},"instructedAmount":{"currency":"CHF","amount":"10.0"},"creditorAccount":{"iban":"LI7108805500000000000"},"creditorName":"Peter Parker","creditorAddress":{"street":"Ingram Street","buildingNumber":"20","city":"Spidercity","postalCode":"12345","country":"DE"},"remittanceInformationUnstructured":"Invoice Nr. 123456"}'

The X-Request-ID can be any UUID created by an online UUID generator tool. The last digit of X-Request-ID influences the state of the created payment. See chapter Encoding. The TPP-Redirect-URI will be used after the user has finished the payment. It is not used in the sandbox.

The execution of the command will lead to the following result:

{
  "paymentId":"2b782d83-5b45-4318-bcb2-3002881495d5",
  "creditorAccount":{
    "iban":"LI7108805500000000000"
  },
  "creditorName":"Peter Parker",
  "_links":{
    "scaRedirect":"not available in sandbox",
    "status":"/psd2/berlin-group/v1/payments/2b782d83-5b45-4318-bcb2-3002881495d5/status"
  }
}

Notice that the scaRedirect is not supported in the sandbox. It will contain the URL for the user to login and approve the payment.

# Get the status of the created payment order

In order to get the status of the created payment order, execute the following command. Remember to replace the path in the url with the received path in the response of your create request:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/payments/2b782d83-5b45-4318-bcb2-3002881495d5/status \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json"

You will receive a response of the following form:

{
  "transactionStatus":"RCVD",
  "fundsAvailable":false
}

# Create a standing order

Use the following command to create a standing order:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/periodic-payments/cross-border-credit-transfers \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "TPP-Redirect-URI: https://www.google.ch" \
--header "PSU-IP-Address: 192.0.0.12" \
--header "Content-Type: application/json" \
--data '{"debtorAccount":{"iban":"LI3808805500000000012"},"instrAmount":{"currency":"CHF","amount":"10.0"},"creditorAccount":{"iban":"LI7108805500000000000"},"creditorName":"Peter Parker","creditorAddress":{"street":"Ingram Street","buildingNumber":"20","city":"Spidercity","postalCode":"12345","country":"DE"},	"startDate": "2023-04-01", "executionRule": "preceding", "frequency": "Monthly", "numberOfExecutions": 12}'

The X-Request-ID can be any UUID created by an online UUID generator tool. The last digit of X-Request-ID influences the state of the created payment. See chapter Encoding. The TPP-Redirect-URI will be used after the user has finished the payment. It is not used in the sandbox.

Note that the startDate must be tomorrow or later.

The field executionRule allows the following values:

  • preceding (execute the payment before the weekend if its execution date falls on a weekend)
  • following (execute the payment after the weekend if its execution date falls on a weekend)

The field frequency allows the following values:

  • Weekly
  • EveryTwoWeeks
  • Monthly
  • EveryTwoMonths
  • EveryFourMonths
  • Quarterly
  • SemiAnnual
  • Annual

Instead of specifying a numberOfExecutions it is also possible to specify an endDate.

The execution of the command will lead to the following result:

{
  "paymentId":"2b782d83-5b45-4318-bcb2-3002881495d5",
  "creditorAccount":{
    "iban":"LI7108805500000000000"
  },
  "creditorName":"Peter Parker",
  "_links":{
    "scaRedirect":"not available in sandbox",
    "status":"/psd2/berlin-group/v1/periodic-payments/2b782d83-5b45-4318-bcb2-3002881495d5/status"
  }
}

Notice that the scaRedirect is not supported in the sandbox. It will contain the URL for the user to login and approve the standing order.

# Get the status of the created standing order

In order to get the status of the created standing order, execute the following command. Remember to replace the path in the url with the received path in the response of your create request:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/periodic-payments/2b782d83-5b45-4318-bcb2-3002881495d5/status \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json"

You will receive a response of the following form:

{
  "transactionStatus":"RCVD",
  "fundsAvailable":false
}

Use the following command to create a consent. The last digit of the X-Request-ID will influence the status of the created consent (See chapter Encoding). Note also that the validUntil date must be in the future, but not more than 180[1] days in the future.

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/consents \
--header "content-type: application/json" \
--header "tpp-redirect-uri: https://www.google.ch" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--data '{"access": ["accounts", "balances", "transactions", "confirmationOfFunds"],"recurringIndicator": true,"validUntil": "2023-03-31","frequencyPerDay": 100}'

The desired access rights can be defined with the parameter "access". The following values are available:

  • accounts
  • balances
  • transactions
  • confirmationOfFunds

Each access type is related to the same account the user is selecting when granting access. Please note that the final access rights may be restricted due to missing roles in the certificate.

You will receive a response of the following form:

{
  "consentStatus":"valid",
  "consentId":"1abd3683-a7a3-491f-a623-79f374fef286",
  "_links":{
    "scaRedirect":"not available in sandbox",
    "self":"/psd2/berlin-group/v1/consents/1abd3683-a7a3-491f-a623-79f374fef286",
    "status":"/psd2/berlin-group/v1/consents/1abd3683-a7a3-491f-a623-79f374fef286/status"
  }
}

The response contains the path for the API to get the state or the full information of a consent.

Use the following command to retrieve the status of the created consent. Remember to replace the path in the request URL with the received path in the response of your create request:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/consents/1abd3683-a7a3-491f-a623-79f374fef286/status \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json"

Find the following response if everything works fine:

{
  "consentStatus":"valid"
} 

Use the following command in order to get the full information of a consent. Remember to replace the path in the request URL as usual:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/consents/1abd3683-a7a3-491f-a623-79f374fef286 \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json"

This should lead to a response of the following form:

{
  "access":{
  "balances":["LI4408805500000000001"],
  "transactions":["LI4408805500000000001"],
  "accounts":["LI4408805500000000001"],
  "confirmationOfFunds":["LI4408805500000000001"]
  },
  "recurringIndicator":true,
  "validUntil":"2020-06-28",
  "frequencyPerDay":100,
  "lastActionDate":"",
  "consentStatus":"valid",
  "_links":{
  }
}

# Get the list of accounts

NOTE: You first have to create a consent in order to be able to retrieve the list of accounts.

The following command retrieves the list of accounts to which an account access has been granted to:

curl --include \
https://developer.vpbank.com/psd2/berlin-group/v1/accounts \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json"

The response has the following form:

{"accounts":[
  {"iban":"LI4408805500000000001","currency":"EUR"},
  {"iban":"LI1708805500000000002","currency":"EUR"},
  {"iban":"LI8708805500000000003","currency":"EUR"},
  {"iban":"LI6008805500000000004","currency":"EUR"}
  ]
}

# Get the transactions of an account

In order to get the list of transactions of an account, you first need to create a consent. Then execute the following command by replacing the consent-ID and the account-ID. You can get the account-ID by retrieving the full information of a consent as described above. Then, choose an IBAN number form the list transactions.

Make also sure that the date range is in the past. We put the URL in quotes because it contains a & character which otherwise would disturb the command line interpreter:

curl --include \
"https://developer.vpbank.com/psd2/berlin-group/v1/accounts/LI4408805500000000001/transactions?dateFrom=2020-03-25&dateTo=2020-04-20" \
--header "accept: application/json" \
--header "X-Request-ID: 99391c7e-ad88-49ec-a2ad-99ddcb1f7721" \
--header "Content-Type: application/json" \
--header "Consent-ID: 1abd3683-a7a3-491f-a623-79f374fef286"

The response should look like this:

{
  "booked":[],
  "pending":[
    {
      "transactionAmount":{
        "currency":"EUR",
        "amount":"2974.5"
      },
      "bookingDate":"2019-01-22",
      "valueDate":"2019-01-23",
      "creditorName":"SampleAccount3",
      "creditorAccount":{
        "iban":"LI4408805500000000001"
      },
      "debtorName":"Anna Musterfrau10",
      "debtorAccount":{
        "iban":"LI3308805500000000005"
      }
    }
  ]
}

# Client Certificate Verification

As mentioned above, you don't need a client certificate to access the sandbox API. But in order to check and verify your productive client certificate, which you will use to access the real API, the following endpoint (https://developer.vpbank.com/psd2/sandbox/certificate/verify_certificate) can be used:

curl --cert client_certificate.crt --key client_certificate.key https://developer.vpbank.com/psd2/sandbox/certificate/verify_certificate

Expected result for a correctly parsed certificate:

{"name":"YourName","roles":["PISP","AISP","PIISP"]}

Any invalid client certificate will result in the error “tlsv1 alert unknown ca” or similar.

# Statistics

The "Uptime", "Downtime", "Daily average time taken per request" and the "Daily error response rate" of our services can be found on our PSD2 Statisctics page (opens new window).

# Release Notes

# 10th September 2019

  • Initial Release V1.0

# 29th January 2021

# 18th February 2023

# 6th May 2024

  • remove unneeded username and password from commands.

  1. Until the adaptation of Art. 10 RTC SCA DvO (EU) 2022/2360 enters into force, 90 days shall continue to apply in the productive version of the openbanking interface. ↩︎

Last Updated: 8/8/2024, 12:41:16 PM