TPP Setup for PSD2 APIs

In order to access PSD2 APIs in sandbox or in production, the TPP must ensure that they are in possession of valid certificates prior to registering using the TPP Client Registration.

In order to access OP PSD2 APIs in sandbox or in production, you need:

  • valid eIDAS certificates (QWAC) for mTLS (in sandbox, it is also possible to use test certificates)
  • keypair for signing JWTs (QSEALC)
  • a publicly accessible JWKS with your QSeal certificate and public key
  • a signed Software Statement Assertion (SSA)
  • a signed registration JWT with the SSA as one of its fields

Read more about certificates.

Once you have the necessary certificates, you can register.

See instructions for TPP Client Registration.

Note: This document assumes cURL version 7.65.0 or higher.

Helper app

Certificate management and TPP registration are complicated operations. To help you get started, we have provided a demo application which you can use to complete these steps in the sandbox environment, and which you may find helpful when building your production application.


Certificates

The TPP must either possess valid eIDAS certificates or use our TPP certificate generation API for generating certificates for use in our PSD2 sandbox environment.

Note that while some certificate vendors offer test certificates, OP's PSD2 sandbox only supports real certificates and certificates from our sandbox certificate API. In other words, 3rd party test certificates are not supported.

Two types of certificates are required:

CertificateAlt NameUse
QWACMTLS cert/keyTransport Layer Security: Mutually authenticated TLS
QSEALCSigning cert/keyDigital Signatures, i.e. signing JWTs.

If the TPP is in possession of valid certificates, they may choose to ignore this step and move on to TPP registration (below).

Certificates can be purchased from Qualified Trust Dervice Providers (QTSPs). The European Union maintains a list of Trust Services. Search the list by Type of Service and select "Qualified certificate for electronic seal" and "Qualified certificate for website authentication", and select the countries you are interested in.

More information on certificates at e.g. Open Banking Europe's FAQ.

Supported QTSPs

We support most QTSPs but below is a list QTSPs that we have onboarded fully. We onboard QTSPs on an as-needed basis. If your QTSP is not on the list, please contact us prior to registration at tpp-support@op.fi and provide us your full certificate chain and CRL URL so we can add them to our list.

  • Actalis (IT)
  • Buypass (NO)
  • D-Trust (DE)
  • I.CA (CZ)
  • InfoCert (IT)
  • Krajowa Izba Rozliczeniowa / COPE SZAFIR - Kwalifikowany (PL)
  • LuxTrust (LU)
  • Microsec (HU)
  • MULTICERT (PT)
  • Quovadis Trustlink (NL)

Mutual TLS requirements

  • TLS 1.2+ and SHA-2
  • RSA or EC key
  • RSA key length min. 2048 and max 4096

Sandbox access

PSD2 APIs are available in sandbox free of charge for both licensed and unlicensed developers. In order to access sandbox you need to take following steps:

  • Sign up to OP developer
  • Create a developer application with wanted PSD2 API products. PSD2 only uses the api key from your developer application.
  • Get PSD2 eIDAS production certificates or use OP sandbox test certificates as described below
  • Register to PSD2 APIs to get your api key and client credentials

Generating test TPP and certificates for sandbox

NOTE! If you opt to use our demo application, you can have it call sandbox certificate generation for you. See README for details.

The certificate generation service provides two certificates: one for emulating QWAC (for establishing mTLS), and another for emulating QSEALC (JWT signing). It will also create a new fictional organization with PSD2 license information. We do occasionally cleanup generated organizations and you may need to generate a new one in that case.

Once the certificates have been generated and delivered to the TPP, the generation service makes the public keys available to services in our sandbox environment. This means that the TPP does not need to publish a JWKS endpoint for their app, unless they want to use keypairs they have obtained from another authority.

Call the certificate generation API as follows:

curl -X POST -v 'https://sandbox.apis.op.fi/psd2-sandbox-tpp-generator/sandbox-tpp?c=<COUNTRY>&cn=<TPP_NAME>&roles=AIS,PIS,CBPII' \
-H 'x-api-key: <APP_API_KEY>' \
-H 'Content-Length: 0' \
-H 'Accept: application/json' \
-d ''

Query parameters

Parameter nameExplanation
cCountry as ISO 3166-1 Alpha 2 (e.g. FI).
cnCommon name of the TPP company (e.g. "Brinklyfy.io").
rolesAn optional comma separated list of PSD2 roles e.g. AIS, PIS and CBPII

Sample Response

HTTP/1.1 201 Created
Date: Tue, 05 Mar 2019 14:03:25 GMT
Content-Type: application/jwk-set+json; charset=UTF-8

{
"privateJwks": {
"keys": [
{
"d": "Je7W5zLu8bO-pJZg1gx0aB7nn-3csejjup4hvS5wc6L4Fk4eJnM6ouViOmf7sw3peenwlLeaVHDBTImY0ohCYDSWNIRcuRjq1vjutx0bh3U4OKaba7ruWGj9j0fxzrue6flOeb3wEXhyLIGGrZZFGcKbuqJw-UnIgt_GV5GeTxH4G-pDnShjFZy_Sbei-JHKxn65SVMcOoxv9UborQdfIWF5qvFDUU-w9iM5x2aGG0Y-7JJI8KpQ_F1nLVnz68r3cpm5A6b2HEDnJkoFifVrhtrs590vKMHPsggCScVGvcHwxKdfUVG8Re3ECZP0q9Db1EyATKpkN1I1XOl7qDw2XB-LXLzLjLqVkBoyRh3Zj1mK0c3LRN1-ENAD9A5WGVAU4xMWMb89Qkqc_MzB_KEOULKR_r7vUjKXMLFGqosW1FHWoyG89Z13O0t2SRyWE1gi5r-VOiite2TybRi9em2O1AdK9TPqAPM4BfqtccFOKvTCJrXPvLYhipEehplMNKthJ7ALgb9V7yMEydtcdTb22qQY4ZqBVrDSjOG0y0QTOUe50F2x7kOhftotFsSK4sxjRuluUmp1fhJ1JA0dBIlzzv5yYLCa7QF9xKTu01m6GxpGbzPskp6DmzYY0_86ZiO97PKc4l4F5g9d68FtsrCVzeuX2WJjOwmIYJNS5x7MpiU",
"e": "AQAB",
"use": "sig",
"kid": "qwac-E4ZXGQ",
"x5c": [
"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"
],
"dp": "tjCRF7hA_H3g4VtKe7SlX3gFFujwMca5mVdeSpk52nvdSoixMNWt8vQ5Xa_Uway6SGMT0KTEo2j80UXebxyIFNp8QPWgKsBGjspB9iwq_MOtzDFyLasJVSfqWDPleN3gihRshb1ezCBde5UuPt2HfzNaBb_upVackXRzX0XjhizcCQHr06_5czQ2B3zWRX_PbScQ_-SZ4zT3k_qgxPWtuJcMCLBUU3vHL71PmKO-muKlR9WEDRyqFI0uBZRWPZWSrhortWT_yLRTKZVxs6AGW34K2rJhO34DFBdwp-uDrJUXXsCp7fC5XXgmx03FFz29SnhWdrrfTwl_qXjazXO9rQ",
"dq": "bOJ5fP4fH-C2sK3FoswD-12EzKe8pU_aUDSJXuCCH1_ACWj4LWyTV8HVyolYr1GVxzyxPPuif2xB9zS96mRVocoRXcbeYCsKQ9qclXnKkubkq7xlsEuQXOsz4VctJorYhwp9UheIPfVRgQO3fZvimxBvA60M8097R6Qe8OXUnVuSAKKHReEPdtFuKZh7jSOB6NhQWzmfQzVvmPaRaqyVBkhxUnE85EJzuoT9DxbciMu8Ecees7Bjl3UPqy5HLR5qea5hSkWqA-ccsBfI2GAjP1gsZrIN920QKk6zZXn2fQce3gKQl6ss7oY_-OvjQj4brWbl3rw5pHY5SM5TDXqSSw",
"n": "m4WH0u5eqK5ggwToSeHFXLtfIGPhLvcjTiKQ7MTRkt1KgZjGRmReEv5_H7J0_YLuZY7QVXWE2GFVx_Y4eJQOrVynR0q62sJjpMZbYeWeF9_WMuB_5rvjrMZ9Vn05ClIOJpmG8Xsi61U1z0cLqSZVvq-k_ZWfO6LSSaRA4eAINfFpxv4WMANVwqjopDuWPXpUBPTl6Y2lSRZRKNYOUQE0JBNUtckKZychCUaTqyAR9zKH0gY0vJS1t55NE4pXkObsoYOfCPvpkQAJ2jD4neQwj9qmLza1KTCtR6mWjbnUlXaJGRkH8EISSKUM2XvZHKSxVjbQHia9CWAmKmvarjWQUqHVh6fJoRgDUE7lsKJZompiWL8MS7weq4OcfbUhABRE2IngjGFNx4WErwukTbtV76vlUZIJu_aE0KJABEBGuuqJVvR6e9u_mGC6ONLq090gqKsBMFyPiDIP3ouMol7n7YN82uB6thCtxSV9l48yg8d4V3gzRdYajudHkzxCX-30wQ1dRU_LWk2URSeO0XqEyozke37UYo8z-t3NealQUtHVytmtvBEgH11nZ-QlDkARELGpJVNj7SVGLHpbU72ZHcHTXLNbW1HUQ-hZdzPO31rZJwDEJT5LoEQddKn7aDHH_27-aXr_1Mk0Y9yOWU-ZdO7LFtKZTWMswlgJgVZvDjE",
"p": "2yA3XSarM98GlUm2bEJXpgJyFXhyKHR9zAGAbWhFn-dOQOscZKWhfuzJRqfiY-OHfURz0QWKV2R5j2O4f9cQ93iMnwfLdUa7QyPLMf0OFt03xBYN_wdL0ano1Fim3JUktfjCItTO38uTn662Zk4TK_Wh37R5nKGpWS8uq3MIQnOth1yaiawnSod7ASaBK-F3dWrfkZoY0uvDpKQ7Cz1viM2caulxxydCs5U33qPsQvHNl27nLZpsTnlHmk5wVNjUEjbAOc8R7TVEPCN-3QanBmHE8Feg-bXba8buTc0u70AI9pg0AsszCopQQovuK7Sp4ndHrevAVxaEQaAo7Aa0bw",
"kty": "RSA",
"q": "tbFKE0CGGq8owQSpmxIhzI46Fz9HsyratciRJGPWn0AaIdyd6TsDg_RUX4zicc76SfiPM5IZyuvShqSx1degdThlXn66CNW05AlPjfKwthmxFRsu9GY8HQrA7W_LvFd3pxy6UX7QB5jn043iOIIafvQ_kM0J6pw7DHPHbd5I9XLGFnBb7zzNr4hpWlbQ6sBRbUqHnQqbsp8FlrGpMxHTPTIC2QFvqLRsDREo1i-Dyb6nngsY1gzCAUTOawcMZmxk4Blp_ulClHpCE2NWCLOch6AugY67Z_2ZQce7xO2tYetjkm0kyIx08lAmekreWQHyyoJlrjyvtR5kdty-EVX3Xw",
"qi": "rSSuouvaNir80vm-DVQc_UwXjq84SOhrjy5WAxuHh4vlowA1KrxNvNzfwl2VVCWRa-4Y3qe-jl93odvllPpT4yM9Q63qzCK6pYayEYls-rYI6dKQRA6bFICwRIfuNGsGcQ21KFedoMGALecUOrC6wOgmC5WsiARR0JYVPyqsnYqVl9wiBSYmyNLm8B0CEjJuURLWpXG5cbnxYL5CUcRJ3a11VsSOpj5r6MOeJwX50HUEMEYw5SiujEBRSGgweRIKptIu-G9rPeII6QbmrmTT31qzzEPlyeBIW7Ek74FRpa8lJN0iYEVM_re6uT3vmaO428jo-3Zd_kIB2yegAEqlbg",
"alg": "RS256"
},
{
"d": "RDEUmyAmTHZ4_ZjLuvZBIgrCsznOmj3nuMld5X7cRqb6GlIOZ-DInA7nqbqW6kYclSW0Fn2gZmit3ZkiagNUmsLHTWP7NwGtRAbjIdBrtFyKV8-t8nQKpd-RNrM0yVr7NC9XWXBi7ZG0U5ho6e-RhDnVPb0JOfpeNUbmZ7X_sbXvWFXeZeguszmvitjafmXnFjzZFAXy_Vx4u7rUam7luYw1EpKeD4kQUiIY9YiH8o_KhH_3s4068y47rE6tZQ2haqTAxXBlR_1PU6JXZTL7gWzNdTL20fUUqW4vnipoxlilGRf5gMi00VK753epDoBFRGPHy6GL4G5_NK1TAduJoiaCU2-aYIxGXfQviGCEIAUlluuIJt1I5KdBBr8bNK5x0WjO8lc6plCjBbUPT75G22rGfEfQDe-1PPw3qZWe6_CC5125hO2K6_Vorr6xa457p7GZM3vku3N7ae_rq6Daf0noZDrIuxvJN8j8i9_7E-nmJ-SM4gTpMSSHoTou9qqpdNSHpLhWuGm2BMzIj8FvrksJusjhmoACOWe80mHc4FsK-MGerNm3wSmZkLogY5LhB44jJHsUlHw8ryGhvrSctw8Rw4Bc5kUbI17-3ECH7f-3BvHSQrWBrgl6Z0RS4alFTzAVIE9_OS845veSUNkL-aPZkdAm2PXN0XPBbhjREYE",
"e": "AQAB",
"use": "sig",
"kid": "qeseal-Jnb0Lw",
"x5c": [
"MIIF7TCCA9WgAwIBAgIEJnb0LzANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJGSTEyMDAGA1UEAwwpT1AgU2VydmljZXMgUFNEMiBBVFkgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcNMjEwMjA5MDIzMDAzWhcNMjYwMjA5MDczMDAzWjBGMQswCQYDVQQGEwJGSTENMAsGA1UEAwwEVGVzdDEoMCYGA1UEYQwfUFNET1AtU0FOREJPWC1UUFAtYmNkYzRkZjgtNDgwNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIt2cJhmVNyPXK2gSgm21vK2va9lvE24AUSLWHNU9W1N54x71Oh3c7EpuRzdjLJx/ZTbYaHbrJj6PgbpCEsj6hh06Hl0mdLWsThtBiILZ3PpNKghugT8Il3zGU10VhdnvRRV9JUReW/W/B6uyEPgXDBPlG+SxPJ4xpDgi7JJ3AATsVhC97rWgNJ1iW9byywb8Mpe8vIA/6q9VaIYt+lWn5pl+TtUgJKJ9v+MSJEm3Hd6VzEUMHCmJ4QGGCFhPq+Jj/OmlcZg3I6SfhYUC0bGhsYTb4wSBdbTOliWEcD8HfKri9tztMB7pZ2G4lbdyc41aTmt5JgFXVEMjCX3g27Aq0Q61namTEjXnO+HSi4A0/zf3Qjyc3j08EqHIX8Nb5/NWNt/n49LN1urAkTfzhvhcjPzMTDH6WGF6wtfiCDpNeeQnL9NZO1wNjM34gDmZjVKFFwfekPeOXc1MPa5tfT9XvBwGkNm/vlnyEZPyTZNqdKXdxYbNI44am8LDlbg54bv/kQCWJ1UQy4stiRccH7HIePK2CdNQCiVruQjvN5XjifdEZPeW7mMO3QR61oBrBFwbM6q0bTYBMNJZpNpXekHFlPJZnCDFWfWukxBnKg/6/RPqNQia+uzOW4VicIdZTxtjIh+1xBLMPRnOCyF0lsVAn7rvJYf0MJuaMh1+q54zsoZAgMBAAGjgecwgeQwCQYDVR0TBAIwADAUBgNVHSAEDTALMAkGBwQAi+xAAQEwawYIKwYBBQUHAQMEXzBdMFsGBgQAgZgnAjBRMDkwEQYHBACBmCcBAwwGUFNQX0FJMBEGBwQAgZgnAQIMBlBTUF9QSTARBgcEAIGYJwEEDAZQU1BfSUMMC09QIFRFU1QgTkNBDAdPUC1URVNUMA4GA1UdDwEB/wQEAwIHgDAlBgNVHSMEHjAcgBSe1xP0/nUkiq6y3gu5f74QDBewzoIED7pSYTAdBgNVHQ4EFgQU9O1+tOvHKKtSLsNWg7SUuCf8q5swDQYJKoZIhvcNAQEFBQADggIBADrPgaPeF/rDOClY/taPeSmoDzIq55DxhUNw54TWhwREFfmIw5U94p/RVJ3eSUxdcxSVQEeWq6dLEcRPW6Oc/VDNnGXfaqWZYu3+1Y4hSJlWZRNvGEjA5hq65huR76ovbzl5/W9dCjsbPnCcBXuwKi4Ql70kCQHIrp1jqeumv5RshztbJtsj7/qP1UBGmNV1OCzuunjSX45PXc60lXMsB70VHGnlvcevMGXGuZPnwgcsLVXa0l0GV7Pj/2Q8cEM76ISQmCuz8yuJlmlccRbou+4nBYhhiiqZGg5dHnVwgmNOJdAMPqXzewJ/AwJOJfeKcEBSXf5DQf7jK30P5M1zZV7B9xt1zqyJNrC0YzerzsRFC4zxBsjFXSq7dltTlAYB367zqh8o/zQQ8KSl5pakUe4h8/IEiUjP7zMcbYCTxOCzyW9A0nHv4qIQXZWAdnQ2+IvGXKvAQmcO7nbfxUbLoKE1hvg44yFcWAK7868VzsU0U7xngm+8kDfZXyqIvKXGYAzRI1Ts8sNaXRRADULuVEygPQSTmGA+vP8cPgRnCbyl71GnAy005ZOZEBfAA/szJFGrPlb1+ApxshQodiXbh3n8Nr8Onl5Xs8bPEmSnACBEChgICpz7x9aLzl8cAfADfNLrJw3HYowM8EEWpRNJT7LlOzRl68zVo5Ng/lLYAODa",
"MIIFbjCCA1agAwIBAgIED7pSYTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEqMCgGA1UEAwwhT1AgU2VydmljZXMgUFNEMiBBVFkgVGVzdCBSb290IENBMB4XDTE5MDIwMTEwMzMwOFoXDTI5MDIwMTEwMzMwOFowQTELMAkGA1UEBhMCRkkxMjAwBgNVBAMMKU9QIFNlcnZpY2VzIFBTRDIgQVRZIFRlc3QgSW50ZXJtZWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAy8xwu7YolrqHe+Nc+S8BQBSKCj4VYRJpv7v2zlY3Nk2MdYwPa4R/VNCENNSJx2s/dEgcnq/Y3Tv6nPyWi5Rt8QkB2a+bWKcrDXpgFeVfPpWFnLUqG7mRrWOWqqVXq5pl6Qs0VWQR8W1GP/3vre8h1XcUosNv5k8cLkKQiAwh+3gOuTAqvl+3l4hF89DZWubbDOMJmaiHjomFxI+5bu9w8PHZHmeT9IgeZLG7/IYllfq6wE8VM1VPLNR2zP2/sOVCpHxo4sbXiskeVzdmvN7FnHfpbslE0/TJYSzjBIzfRH6wwbrMARicfD3hmmw921tUORO00mEU++OrUqaAJd50I7RObdqbISphUCyUdPoujvMNIZezjHkiME0w1W1jg9tU1qh0+yBb/8mz8VOqYnNGwRjt2IuSzC65n/Uq5q+DgFA+i9jeL5W6oIPNLsGzVAPnysDZcxxZcX2PA1XxomvUf4mvyn3H67LiZTsCNiIOO+LJxjD95clYGcfnVGDzVs2z2r4ldQ1sOSqCn5wuOHtkfqzuzO8o23z7nK2dPDYXL5y8pp0otPOSGCp72W6Ds67w92NVSaQ8q/4Nj6C+dhqpOdiCRsiwPb+GzbB8eZvuGoFqugJz665xm2P+mK12dScOnCj7Cr+BT0lpnOPdas64XEDQj7n0tzIxksdpARXHt1sCAwEAAaN2MHQwDAYDVR0TBAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwNQYDVR0jBC4wLIAU9XrGSy6qu3tdo3zQxZGmzD6fRLqCFC2sa019f+DVMMlPMn4K/pnsmKIbMB0GA1UdDgQWBBSe1xP0/nUkiq6y3gu5f74QDBewzjANBgkqhkiG9w0BAQUFAAOCAgEAW5JY0ep4uAFYRdoSEpxIdH9yu4FDsRxceWzufFYsyTTM5AFw0uKFJpetAkhh8oCUys7Bm9LdtcM7tvPPOXnFKc6vRfR69cZqNJXoxQh7iq0HkE18oMiW3f18+pbyUnXC9FLQtqdXPKOYeIgZAKMOEvcURkPMOC3wMm3o7sxwJ960jtriYqK5C0guB8OJ7cJQOJ4wj++qyRivoEgm3O0/m5VmfTrM1nBX4pxYyTiNnLWdnyDJ6DG9J0DLNkY3uqD+QhGczAkG4jVisjrOmyn7Md116B0oJPUR9smUNhNR+JHTksXWSdlHz7ofLXfJaKmoQK/rzFIuLj2WxG/TsKv0tGfKqbZPZAKAhL/gqEWp5gzkym1lFXDSX2qi+6Co6OWRXSgQJXd1dxPTxhCXxkVW3YRXNvgq0xnlyNa7ONzu1R/MlwOTJmqOSiic2kG7A/1MhEm76dhb36cnd3fZ6yihPFnLFRDTuaYC9zXhm7Ri5IE96xdHD0d+RlLjVlR8Ugfsh995oKpQKKpmugksFqg88qMcm6DLMmomhEapeaKFMf+JiqunwHp3JL76Pw6rh5VNIeSey8wW31sHbYz31TmYWulAAE40231tAL/D/Gyt/50Nrq8VpyU85Z6+x7kp3PVb1STx8ZhN813AYDgJTPYtIvP4SVIbkmpyQ4SR+G6E7sc="
],
"dp": "wCkpHLQ_OAK1CmxtdGWyJZZWq2SJZSrgDIScDI_c0XwjhEng-6QH9tBEfv68vEusdWkeiYv6R8qnPjnu7m_Jc4dBhO65hXCzTiHij4DXVMpyea5C3skfWwxWvxPL0t910_PHw1PICkkbBWf4xNb5jaLJuJYYl4_gOVG3mW1shjOyLuy2ODwTqtxJh2G1NjwfIVPc7AGVrhjV63EcbXunmwuw7r92qiPjs8VOEANpw0cevSy6ZRZA94ogG1p-TD-fLiJ7LhXXchrsRHk3ZAkk6V5xKfrlc2u2lGGeM18Ji6JS33_7JB8baUuaNjLcRznoMyLZqqsMDxmjWa3X42y_AQ",
"dq": "LB_uS2Dulp1B0pGv0vkSVO_LvwBKA5flTkbQGq2vUdEKrRY59QC7uYNIxTr_RCqgBhtP4baXoKjbopdjrsERFs2O_8KGFfb57Z7nJsdAxYkGN7hDElaoVIgk3m3JBXKR7Viaup2oU49BdZmSSi1XEjuagrkojJ9ALcZbQd20T9QwHoiqQGVPfLD3_a6i6u-foTJxWeHxmtEW2WJucYQccg3QiB02nHB_xmO63Gy0D6pWpa5i040LAb-b9KzNZ2JCzGtToWLxRxXLzWCx6RraT7etvs4eEaaekdqXr0O4HyRJ2yWqXTjPeRddDsgiVDCdZWn5_TmGTGpuDhoiwH-m0Q",
"n": "i3ZwmGZU3I9craBKCbbW8ra9r2W8TbgBRItYc1T1bU3njHvU6HdzsSm5HN2MsnH9lNthodusmPo-BukISyPqGHToeXSZ0taxOG0GIgtnc-k0qCG6BPwiXfMZTXRWF2e9FFX0lRF5b9b8Hq7IQ-BcME-Ub5LE8njGkOCLskncABOxWEL3utaA0nWJb1vLLBvwyl7y8gD_qr1Vohi36VafmmX5O1SAkon2_4xIkSbcd3pXMRQwcKYnhAYYIWE-r4mP86aVxmDcjpJ-FhQLRsaGxhNvjBIF1tM6WJYRwPwd8quL23O0wHulnYbiVt3JzjVpOa3kmAVdUQyMJfeDbsCrRDrWdqZMSNec74dKLgDT_N_dCPJzePTwSochfw1vn81Y23-fj0s3W6sCRN_OG-FyM_MxMMfpYYXrC1-IIOk155Ccv01k7XA2MzfiAOZmNUoUXB96Q945dzUw9rm19P1e8HAaQ2b--WfIRk_JNk2p0pd3Fhs0jjhqbwsOVuDnhu_-RAJYnVRDLiy2JFxwfsch48rYJ01AKJWu5CO83leOJ90Rk95buYw7dBHrWgGsEXBszqrRtNgEw0lmk2ld6QcWU8lmcIMVZ9a6TEGcqD_r9E-o1CJr67M5bhWJwh1lPG2MiH7XEEsw9Gc4LIXSWxUCfuu8lh_Qwm5oyHX6rnjOyhk",
"p": "4NJ8xdsgvdVbPjvG0ohUSb7ngxX1XljLPV7g2vtKOZaCA0dRaPPzi7NYxEYtdYuhPSfL4FAovwRiBiXKg1I5oqBhKWNdnXpyNg-UAVTtA5dSktUPx-Wq57QuQ-fF-L1Hh2SF6zaHHtzaQyO_kKJSy44JVqYQu_ZPc9WFNL5v0e8lq3dJEkp-GA6SQr0T7OvXxXFnd4wuuTYONIigtzUcHAVRzE35BjDDMpGFZhXDC_78SlglhRW-sSbvkpW5io5-aulyqGeQ5BQHKccXmxgZF6I7j00RZTTEQoFdU5DXLHB0ayMAPPUaSggPN7SfYPztHvsoymxTCjCjJne1M7fpsQ",
"kty": "RSA",
"q": "ns2QpjahNpJhViuAar4V2Lkgy4HT6WvWz9aXAZJRXKYQAAM_gRBm8AtHVq39y4-0qIU-WThWBpYIiiZ-x2mEysGw9IWUNWFA0RXbeOgCp24vTWIUyVZ-2ZJPNkYdV77fowbG8NnGYOIgZvLeOoh-oV6fSLuGuxV2zmkAT_oDggujtDWLcbmJ4gjIK4FCdhGGRHbpe7r-vtX9R4Sfa1s1iTY3eQJtnvxgQUeEg828E28e2A-jzi0FsM4BPbnoKO7Lmb4KIcafrGzLfrpKFX3edxKpaIG9z4l22tF9LBs1Q7z8BxQf3k4Pmm1Yyy-d4NUIREICS1hc-uvRq-9BLsqY6Q",
"qi": "3g_JRVk9TBBIw5An6jSM3av2lU7S8K0yL2XxpmiRuZYl52l2PSnHvxV7QmQpA0XDr0p8ECNL0UCkfBN6mAoyJ7nOBWZbO4M-Cp2WYaYo7TiWA1kShcyNqRVUxm8MtOWCtOBCXUmwskZeEdehmt3zyFuG-gKZxf4sW4mNCUXH0zjiORv-mOITF-HboJgd4kgzHoYzqwPS_gQIjdhTuexfHmuUXBzngmz2CcZRYek5lOrPPR2hFoDc4GZTi-Q7gLKU7rP-QLgbjz26jEGIZDzmKelE47g-nWOwWUK2XZX0MyoFCBsKFcWqnPGT4tUtgKFVGUNn8flE1HnaARkeK9mLpQ",
"alg": "RS256"
}
]
},
"tppId": "OP-SANDBOX-TPP-bcdc4df8-4804",
"publicJwksUrl": "https://example.generated.tpp/OP-SANDBOX-TPP-bcdc4df8-4804/public-jwks.json"
}


The response contains everything you need for using PSD2 sandbox. See JWKS for more info on JWKs.

Some notes on each item:

FieldExplanationNote
privateJwksPrivate JWKs for your appContains a private JWKS for the generated TPP. It contains both RSA and EC keys and for both key types separate key for QWAC and QSEALC.
publicJwksUrlWKS available to sandbox servicesThis URL contains the above public keys for our sandbox services. In other words, TPP's are NOT required to set up a published JWKS endpoint for testing. If the TPP does not create their own JWKS endpoint, this value must be passed on in the registration call (field software_jwks_endpoint).
tppIdThis is the generated organization (TPP) that has requested roles (by default AIS, PIS and CBPII). Note that this is the field org_id in registration SSA. This is also the organization identifier in the certificate without the PSD prefix. 

Save this json response and extract the private jwks as you'll need the information to register as well as to sign requests. Your QWAC is the first certificate of the JWK x5c array.

Using the JWKS

It's recommended that you use a library that supports JWKS natively such as Nimbus JOSE in Java and panva/jose in NodeJS which have been tested to work well.

Refer to our example registration app on how to register.

Sandbox endpoints

ServiceHost
Authentication and authorizationhttps://authorize.psd2-sandbox.op.fi/oauth/authorize
JWKS endpoint for ID token signature verificationhttps://authorize.psd2-sandbox.op.fi/oauth/jwks/PSD2_OIDC
Tokenhttps://psd2.mtls.sandbox.apis.op.fi/oauth/token
Business APIs base URLhttps://psd2.mtls.sandbox.apis.op.fi
JWKS URI for validating payment response signatureshttps://sandbox.apis.op.fi/psd2/sandbox/jwks/payments/jwks.json

Production access

Following the regulation, using PSD2 APIs is free of charge also in production. However, a Third-Party Provider has to apply for an AISP/PISP license from a financial authority (e.g. FIN-FSA in Finland) and obtain valid QWAC and QSEAL certificates.

In order to access production you need to do following steps:

  • Test your application against PSD2 sandbox (Reguires sandbox registration. See above)
  • Register to PSD2 APIs to get your api key and client credentials

Production endpoints

ServiceHost
Authentication and authorizationhttps://authorize.op.fi/oauth/authorize
JWKS endpoint for ID token signature verificationhttps://authorize.op.fi/oauth/jwks/PSD2_OIDC
Tokenhttps://psd2.mtls.apis.op.fi/oauth/token
Business APIs base URLhttps://psd2.mtls.apis.op.fi
JWKS URI for validating payment response signatureshttps://apis.op.fi/psd2/jwks/payments/jwks.json

Production issues

During office hours, you can contact us about any production issues via email at tpp-support@op.fi. Please provide us with the following information:

  • Date and time of the issue (including time zone)
  • Description of the issue
  • Full error response
  • authorizationId
  • clientId
  • x-fapi-interaction-id header value
  • authorization request JWT (when issue is with /oauth/authorize)

Outside office hours, please report production issues on op.fi and send the ticket number to tpp-support@op.fiInclude the following information in the report:

  • System: "PSD2 AWS API" or "PSD2 Authorization" depending on whether the issue is with API call or with authorization
  • Service: "PSD2 Payment Initiation Service", "PSD2 Account Information Service" or "PSD2 Confirmation of Funds"

Do not include sensitive information such as client secret, API key or access token, when contacting us.


TPP Client Registration

To access PSD2 APIs, TPPs must register with the ASPSP. The registration process for OP's PSD2 APIs is fully automated and needed to ensure secure communication with the APIs. More speficically it serves the following purposes:

  • Delivering an API Key & Client Credentials to the TPP
  • Keeping track of the TPPs using PSD2 APIs
  • Submitting important security information, e.g. JWKS endpoints.

In sandbox as well as in production, the TPP must take the following actions:

  • Publish a publicly available JWK Set in standard JWKS Set format. If using a sandbox test certificate, you may use the publicJwksUrl received in the sandbox TPP generation response. Note: If you update the contents of the JWK Set, it will take roughly two hours to propagate to our systems.
  • Build the SSA (Software Statement Assertion) and sign it with a QSEALC/emulated signing key
  • Build the registration JWT, include the signed SSA JWT in it, and sign the registration JWT with the same QSEALC/emulated signing key
  • POST the registration JWT to the API.

Registration call

To register, you must construct, sign (with QSEALC key) and POST a JSON Web Token (JWT) to our TPP registration endpoint. This happens via MTLS, so you need to perform handshake using your QWAC key & certificate.

POST /tpp-registration/register HTTPS/1.1
Host: psd2.mtls.sandbox.apis.op.fi
Content-Type: application/jwt
Accept: application/json
x-api-key: <APP_API_KEY> (Only required in sandbox)

eyJraWQiOiJTYW9lMVEiLCJhbGciOiJFUzI1NiJ9.eyJpYXQiOjE1OTY2MTgxNTUsImV4cCI6NDc1MjMxMDc1NSwiYXVkIjoiaHR0cHM6Ly9vcC5maS8iLCJqdGkiOiJhYmQ2ODY5NS1iNzViLTQxZDMtOWQ1YS0zYzI3N2M4YWVmNTUiLCJyZWRpcmVjdF91cmlzIjpbImh0dHBzOi8vdGVzdHRwcC5yZWRpcmVjdC51cmwiLCJodHRwczovL3Rlc3R0cHAucmVkaXJlY3QyLnVybCIsImh0dHBzOi8vdGVzdHRwcC5yZWRpcmVjdDMudXJsIl0sImdyYW50X3R5cGVzIjpbImNsaWVudF9jcmVkZW50aWFscyIsImF1dGhvcml6YXRpb25fY29kZSIsInJlZnJlc2hfdG9rZW4iXSwic29mdHdhcmVfc3RhdGVtZW50IjoiZXlKcmFXUWlPaUpUWVc5bE1WRWlMQ0poYkdjaU9pSkZVekkxTmlKOS5leUpwYzNNaU9pSlBVQzFVUlZOVUxWUlFVQzFpT1dFeE5UaGpOQzAyT0RBNElpd2lhV0YwSWpveE5UazJOakU0TVRVMUxDSmxlSEFpT2pRM05USXpNVEEzTlRVc0ltcDBhU0k2SWpsbU9EUXdaV1V6TFRnNFpUWXRORGcxWlMxaFpHSXlMV1F5TVdOaE9ERmlORGMyWXlJc0luTnZablIzWVhKbFgyTnNhV1Z1ZEY5cFpDSTZJalUxTlRrNE9HRmlMVEl6TXpBdE5HUXlaUzFoWkRrMExUbG1Oek5sTkdabU9XTmlaaUlzSW5OdlpuUjNZWEpsWDNKdmJHVnpJanBiSWxCSlV5SXNJa0ZKVXlJc0lrTkNVRWxKSWwwc0luTnZablIzWVhKbFgycDNhM05mWlc1a2NHOXBiblFpT2lKb2RIUndPaTh2Ykc5allXeG9iM04wT2pnNE9Ua3ZMbmRsYkd3dGEyNXZkMjR2WldOa2MyRXZhbmRyY3k1cWMyOXVJaXdpYzI5bWRIZGhjbVZmYW5kcmMxOXlaWFp2YTJWa1gyVnVaSEJ2YVc1MElqb2lhSFIwY0RvdkwyeHZZMkZzYUc5emREbzRPRGs1THk1eVpYWnZhMlZrTDJWalpITmhMMnAzYTNNdWFuTnZiaUlzSW5OdlpuUjNZWEpsWDJOc2FXVnVkRjl1WVcxbElqb2lkR1Z6ZEMxamJHbGxiblFpTENKemIyWjBkMkZ5WlY5eVpXUnBjbVZqZEY5MWNtbHpJanBiSW1oMGRIQnpPaTh2ZEdWemRIUndjQzV5WldScGNtVmpkQzUxY213aUxDSm9kSFJ3Y3pvdkwzUmxjM1IwY0hBdWNtVmthWEpsWTNReUxuVnliQ0lzSW1oMGRIQnpPaTh2ZEdWemRIUndjQzV5WldScGNtVmpkRE11ZFhKc0lsMHNJbk52Wm5SM1lYSmxYMk5zYVdWdWRGOTFjbWtpT2lKb2RIUndjem92TDNSd2NDNWpiMjBpTENKdmNtZGZibUZ0WlNJNklsUmxjM1FnVkZCUUlpd2liM0puWDJsa0lqb2lUMUF0VkVWVFZDMVVVRkF0WWpsaE1UVTRZelF0Tmpnd09DSXNJbTl5WjE5amIyNTBZV04wY3lJNlczc2libUZ0WlNJNklsUlFVQ0JEYjI1MFlXTjBJaXdpWlcxaGFXd2lPaUpwYm1adlFIUndjQzV2Y21jaUxDSndhRzl1WlNJNklpc3pOVGd4TWpNME5UWWlMQ0owZVhCbElqb2lVM1Z3Y0c5eWRDSjlYWDAuRURKZXRLQWduamVySEF5OFhlYkwwR2hKZWhwWXVWeGJGa3hlRmFuWlJHYk9uUkNDLU4xSUw1QU5MemcxOFQxa0VRdWhjMUw4R19JeXlFOWRZOFU3VHcifQ.IU5bJKu2ig1Vh07dK25MamEuqWgF0ohx4WQq9XQtWKSgXdgCvB8_G79bbUnNi0FJuZWf5pLW0ynxurZ6CCG_xQ

Client Registration Request

The registration request and software statement are signed with ES256 or RS256, using your QSEALC or generated signing key (in sandbox only).

Structure

{
"kid": "Saoe1Q",
"typ": "JWT"
"alg": "ES256"
}
{
"iat": 1596618155,
"exp": 4752310755,
"aud": "https://op.fi/",
"jti": "abd68695-b75b-41d3-9d5a-3c277c8aef55",
"redirect_uris": [
"https://testtpp.com/redirect-url1",
"https://testtpp.com/redirect-url2",
"https://testtpp.com/redirect-url3"
],
"grant_types": [
"client_credentials",
"authorization_code",
"refresh_token"
],
"software_statement": "eyJraWQiOiJTYW9lMVEiLCJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJPUC1URVNULVRQUC1iOWExNThjNC02ODA4IiwiaWF0IjoxNTk2NjE4MTU1LCJleHAiOjQ3NTIzMTA3NTUsImp0aSI6IjlmODQwZWUzLTg4ZTYtNDg1ZS1hZGIyLWQyMWNhODFiNDc2YyIsInNvZnR3YXJlX2NsaWVudF9pZCI6IjU1NTk4OGFiLTIzMzAtNGQyZS1hZDk0LTlmNzNlNGZmOWNiZiIsInNvZnR3YXJlX3JvbGVzIjpbIlBJUyIsIkFJUyIsIkNCUElJIl0sInNvZnR3YXJlX2p3a3NfZW5kcG9pbnQiOiJodHRwOi8vbG9jYWxob3N0Ojg4OTkvLndlbGwta25vd24vZWNkc2Evandrcy5qc29uIiwic29mdHdhcmVfandrc19yZXZva2VkX2VuZHBvaW50IjoiaHR0cDovL2xvY2FsaG9zdDo4ODk5Ly5yZXZva2VkL2VjZHNhL2p3a3MuanNvbiIsInNvZnR3YXJlX2NsaWVudF9uYW1lIjoidGVzdC1jbGllbnQiLCJzb2Z0d2FyZV9yZWRpcmVjdF91cmlzIjpbImh0dHBzOi8vdGVzdHRwcC5yZWRpcmVjdC51cmwiLCJodHRwczovL3Rlc3R0cHAucmVkaXJlY3QyLnVybCIsImh0dHBzOi8vdGVzdHRwcC5yZWRpcmVjdDMudXJsIl0sInNvZnR3YXJlX2NsaWVudF91cmkiOiJodHRwczovL3RwcC5jb20iLCJvcmdfbmFtZSI6IlRlc3QgVFBQIiwib3JnX2lkIjoiT1AtVEVTVC1UUFAtYjlhMTU4YzQtNjgwOCIsIm9yZ19jb250YWN0cyI6W3sibmFtZSI6IlRQUCBDb250YWN0IiwiZW1haWwiOiJpbmZvQHRwcC5vcmciLCJwaG9uZSI6IiszNTgxMjM0NTYiLCJ0eXBlIjoiU3VwcG9ydCJ9XX0.EDJetKAgnjerHAy8XebL0GhJehpYuVxbFkxeFanZRGbOnRCC-N1IL5ANLzg18T1kEQuhc1L8G_IyyE9dY8U7Tw"
}
FieldTypeDescription
algstringThe signing algorithm used. ES256 or RS256
typstringType of the token. Always JWT.
kidstringHints at the key pair used with this signature. Helps the consumer fetch the right public key for validation.
iatnumber / integerThe time at which the JWT was issued. In epoch seconds.
expnumber / integerRequest expiration time. In epoch seconds.
audstringRequest audience (The ASPSP). Use value https://op.fi/.
jtistringJWT ID: a unique identifier for the ID. MUST be unique to prevent replay attacks.
redirect_urisarray / stringArray of whitelisted redirection URI strings for use in redirect-based flows (i.e. authorization code).
grant_typesarrayArray identifying the different grant types the TPP will use.
software_statementjwtSSA JWT signed by TPP in compact serialized format.

Software Statement Assertion

The Software Statement Assertion is a JWT created and signed by the TPP. It is signed with the TPP's QSEALC or the associated signing key received from OP's certificate generation service (only in sandbox). The signature is created using ES256 or RS256 algorithm and must match the registration request.

If you have a generated certificate, you may use the "publicJwksUrl" in the software_jwks_endpoint field: you don't need to set up a public JWKS endpoint to get started in the sandbox.

{
"iss": "OP-SANDBOX-TPP-b9a158c4-6808",
"iat": 1596618155,
"exp": 4752310755,
"jti": "9f840ee3-88e6-485e-adb2-d21ca81b476c",
"software_client_id": "555988ab-2330-4d2e-ad94-9f73e4ff9cbf",
"software_roles": [
"PIS",
"AIS",
"CBPII"
],
"software_jwks_endpoint": "http://testtpp.com/.well-known/ecdsa/jwks.json",
"software_jwks_revoked_endpoint": "http://testtpp.com/.revoked/ecdsa/jwks.json",
"software_client_name": "My Awesome APP",
"software_redirect_uris": [
"https://testtpp.com/redirect-url1",
"https://testtpp.com/redirect-url2",
"https://testtpp.com/redirect-url3"
],
"software_client_uri": "https://tpp.com",
"org_name": "Test TPP",
"org_id": "OP-SANDBOX-TPP-b9a158c4-6808",
"org_contacts": [
{
"name": "TPP Contact",
"email": "info@testtpp.com",
"phone": "+358123456",
"type": "Support"
}
]
}
FieldTypeDescription
issstringTPP ID.
iatnumber / integerThe time at which the JWT was issued. In epoch seconds.
expnumber / integerSSA expiration time. In epoch seconds.
jtistringJWT ID, e.g. 5e63fcae-0c46-4be3-bbf8-eb6eb9bb14a1.
software_client_idstringUnique Client ID of the software client. Format must be UUID, e.g. 2dc3102d-8f49-4c57-8de8-a63ccade3766
software_client_namestringHuman-readable name of the software client.
software_client_uristring / URIWebsite or resource root URI.
software_jwks_endpointstring / URIEndpoint that exposes all active signing public keys and certificates for the software. When you implement your own JWKS endpoint, ensure that it contains at least the JWK for validating registration JWT and the JWK for validating authorization JWT. Both of these JWKs MUST contain x5c with the QSEALC certificate. The contents of this endpoint must be in JWK Set format. For Sandbox, this field may contain the URI received during certificate generation.
software_jwks_revoked_endpointstring / URIEndpoint that contains all revoked JWKs for the software. Same format as software_jwks_endpoint.
software_redirect_urisarray / stringContains all redirect URIs for the software client.
software_rolesarray / stringPSD2 roles this software is authorized to perform.
org_idstringProduction: Unique ID for the software creator as assigned by a national competent authority. Must match the organizationId in the certificate, excluding the PSD prefix. Sandbox: The TPP ID received from the certificate generation service.
org_namestringLegal Entity Identifier or other known organisation name.
org_contactsarray / objectMandatory JSON array of objects containing a triplet of name, email, and phone number. At least email attribute is required in each array object. That address is used to inform TPP's about updates and service breaks etc.

Registration Response

Once successfully registered, you will receive a JSON response containing your client information. Keep the response secure, as it contains the client credentials for accessing PSD2 APIs.

Sample response body

{
"client_id": "4vPsWdBi5d6G2dezEmfvh",
"client_id_issued_at": 1552553405,
"client_secret": "jqGQqZ6s6AXahdiMVFj9N",
"client_secret_expires_at": 0,
"api_key": "cGY7jn9z8Y141GZWMu6pNlCT0tfYlD6PM",
"client_name": "software-client-1",
"redirect_uris": [
"https://localhost:8181",
"https://tpp-demo-app.demo/oauth/access_token"
],
"grant_types": [
"client_credentials",
"authorization_code",
"refresh_token"
],
"software_id": "6fdd0ca8-33f1-4b84-932a-c92e2f179bc8",
"scope": "openid accounts payments",
"jwks_endpoint": "https://example.tpp/jwks.url",
"software_roles": [
"AIS",
"PIS"
]
}
Field NameTypeDescription
client_idstringClient ID of the TPP application.
client_id_issued_atDate / timestampTime of issuance of the client credentials. Seconds since Epoch.
client_secretstringClient secret of the TPP application.
api_keystringAPI Key of the TPP application. In sandbox, this is a replayed value as the API key has already been received from OP Developer.
redirect_urisarray -> string / URIRedirect URIs registered to the application.
grant_typesarray -> stringGrant types allowed to the application.
software_idstringYour registered application Software ID.
scopestringSpace-delimited list of scopes allowed to the application. Possible values: openid, accounts, payments, fundsconfirmations.
jwks_endpointstring / URIJWKS endpoint registered to the application.
software_rolesarray -> stringLicense-based roles registered to the application. Possible values: AISP, PISP, CBPII.

Verifying your registration

After registering successfully, you can verify the validity of your certificates and API key with the following cURL call (assuming you have AIS access):

curl -vk --key key.pem --cert client.crt https://psd2.mtls.sandbox.apis.op.fi/oauth/token -d 'grant_type=client_credentials&scope=accounts&client_id=<client_id>&client_secret=<client_secret>'

If the certificates and client credentials are valid, you will receive a 200 response:

{
"token_type" : "bearer",
"access_token" : "Axqx362CnSmLABgzqcBasG0pxBj9",
"scope" : "accounts",
"status" : "approved",
"expires_in" : "86399",
}

If you get a handshake failure that signals an issue with your certificate or it's trust chain. Please make sure you are using correct key and certificate in the TLS handshake.

If you received a response similar to the sample above, you are ready to start working on authorization. See our workflow documentation for Account Information, Payment Initiation and Confirmation of Funds services.

Deleting Clients

If your client has been compromised or you want to replace it with another one e.g. to include new redirect url's, you can delete an existing client as follows:

1. Create access token with scope 'clientmgmt':

POST /oauth/token HTTP/1.1
Host: psd2.mtls.sandbox.apis.op.fi
Content-Type: application/x-www-form-urlencoded
Accept: application/json
grant_type=client_credentials&scope=clientmgmt&client_id=<client_id>& client_secret=<client_secret>

2. Use the access token in actual DELETE request:

DELETE /tpp-registration/register/<client_id> HTTPS/1.1
Host: psd2.mtls.sandbox.apis.op.fi
Content-Type: application/jwt
Accept: application/json
x-api-key: <api_key>
Authorization: Bearer <access_token>

NOTE: The requests happen via MTLS, so you need to perform handshake using your QWAC key & certificate.

Field NameTypeDescription
client_idstringClient ID of the TPP application.
api_keystringAPI Key of the TPP application
access_tokenOIDC access tokenvalid access_token for the client in question, must be generated using client credentials grant

Access token generation example

HTTP 204 response is sent upon successful client removal.

Renewing certificates

Renewing certificates is typically as easy as rolling in new key entry in JWKS for QSeal and use the new key for signing. Note that your JWKS file should contain both old and new key entry with unique kid. For QWAC just starting to use it. It is recommended though that you first test them before rolling to production use. QTSPs sometimes change the certificate hierachy with new intermedia or root certificate and the new ones might not yet be updated to OP PSD2 API trusted certificates.