# 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
- Differences between the sandbox and the productive API
- Encoding
- Getting started with curl
- Create a payment order
- Get the status of the created payment order
- Create a standing order
- Get the status of the created standing order
- Create a consent to retrieve account information
- Get the status of the created consent
- Get the full information of a consent
- Get the list of accounts
- Get the transactions of an account
- Client Certificate Verification
- Statistics
- Release Notes
# 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
}
# Create a consent to retrieve account information
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.
# Get the status of the created 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"
}
# Get the full information of a consent
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
- Add "debtorAccount" parameter to the payment initiation request (see chapter Create a payment order).
# 18th February 2023
- Allow for payment initiation of periodic-payments (standing orders). See chapter Create a standing order.
- Adjust the documentation of the maximum duration a consent may be valid. See chapter Create a consent to retrieve account information.
# 6th May 2024
- remove unneeded username and password from commands.
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. ↩︎