Version:  1.0.0
State:  Published
Environment: Sandbox
Base URI:
Categories: PARTNER



LUXHUB One provides a unified interface to access the PSD2 APIs of multiple providers, establishing a common data model, security profiles and authorization flows to overcome the complexities caused by differing implementation standards.

Therefore, as a consumer of LUXHUB One, you are able to seamlessly integrate the APIs of various PSD2 providers and thus provide easy access to PSD2 account information and payment initiation services to your customers.

LUXHUB One is available to PSD2-regulated providers, including:

  • PSD2-licenced TPPs, who have been registered as a Payment Initiation Service Provider (PISP) and/or Account Servicing Payment Service Providers (ASPSP) with their National Competent Authority (NCA or Regulator), and

  • Financial regulated entities, such as banks, Payment institutions (PI) and Electronic Money institutions (EMI)


A. Where is LUXHUB One available?
B. How to integrate LUXHUB One
C. Account Information Service
D. Payment Initiation Service
E. Additional technical considerations
F. Changelog/versions


A. Where is LUXHUB One available?


LUXHUB One covers all major banks and other PSD2 providers in Luxembourg, in addition to several Belgian and French banks.


Market Account information Payment initiation
Luxembourg ALL ALL


B. How to integrate LUXHUB One


Your onboarding as a new consumer of LUXHUB One involves certain technical and business steps, which are required in order to ensure a smooth and compliant start:

Step 1: sign an agreement with LUXHUB
Step 2: be set up as a LUXHUB One API client
Step 3: register with relevant providers (or provider onboarding)
Step 4: get access to the API in both Sandbox and Production modes

Step 1: Sign an agreement with LUXHUB

This step comes after the usual sales procedure that ensures that you are aware of all the functionalities and capabilities of LUXHUB One, as well of all the necessary steps involved in becoming a consumer; potential fallacies; roles and responsibilities of each party; project management items and pricing of the service. The contract will formalize all of these aspects, so they can be agreed upon by each party and include various annexes related to the technical procedures to follow during the onboarding and normal operation during the product life cycle.

If you did not yet start with this process, feel free to get in touch with the LUXHUB sales team.


Step 2: Initial technical set up with LUXHUB

This step involves granting you access to the LUXHUB One API endpoints, based on the contractual relationship established during the previous step. This step is mostly technical and involves setting up a secured access to consume the API.

Your identification and authentication towards the LUXHUB One platform is controlled at two levels: protocol level, using MTLS authentication, and application level, using OAuth Client Credentials. In addition, message-level signing is provided via http-signing of all exchanges via the API.

a) Consumer registration on the LUXHUB platform: the API use involves server-to-server communication only and does not directly involve the end-user in authorizing access - hence, the API authorization is provided by the use of client credentials access token. This enables the platform to identify you and verify your rights to access the different API services.

The first technical step, as part of your consumer onboarding, is to create and application on our Developer Portal, assign the LUXHUB One API to this application and to generate OAuth Credentials.

b) MTLS setup: this requires you to use an SSL client certificate to authenticate yourself towards LUXHUB One as a registered and approved consumer of the API.

The SSL certificate that you will have to use is issued by LUXHUB's own Certification Authority. You can download MTLS certificate and MTLS key from the Developer portal as part of your application.


Step 3: Onboarding with relevant providers

Consumer eIDAS certificates (QWAC and QSEALC) will be used to identify LUXHUB One towards the API providers. The protocol below details how you will be able to provide these certificates and how you will be onboarded with the different providers that you are interested in accessing.

a) eIDAS certificates protocol:

In order to avoid sharing private keys, LUXHUB One will create CSR requests for each consumer certificate that it needs to have for its operation, i.e. QWAC and QSEALC. These CSRs will be created with the required eIDAS profile and data in order to identify you for the purpose of PSD2 API usage. You will create, with a QTSP, QWAC and QSEALC certificates, and provide them to LUXHUB:

1. LUXHUB creates a CSR for eIDAS profiles, both QWAC and QSEALC – private keys ALWAYS remain with LUXHUB

2. LUXHUB sends you the CSRs

3. You get, from a QTSP, eIDAS certificates based on the CSR LUXHUB provided

4. Certificates are returned to LUXHUB

5. You maintain full control over the certificate (you can revoke it, etc.); you also have the responsibility to manage certificate renewal or revocation (by restarting the aforementioned process)

6. LUXHUB configures these certificates in the system and uses them to identify you towards the ASPSP in the context of the PSD2 framework.

You will need to outline the providers whose PSD2 services you are interested in consuming to the LUXHUB One delivery team. The LUXHUB One delivery team will be in charge of registering you, as a TPP, with each of these providers. This process might be automatic with some providers, or manual for others. Also, as part of this process, the LUXHUB delivery team will need to register you as a TPP client for the provider's API (first in the Sandbox environment and then in Production).

It is important to note that the majority of providers require a real eIDAS from TPPs for registration, even in Sandbox mode - the PSD2-regulated way of "providing Sandbox access to TPPs in process of registration" is considered to be a complicated manual process that it is not able to be supported at this stage. 

On the other side, there are providers who will allow the registration of TPPs to Sandbox access even without an eIDAS certificate. While this is possible and supported, it is recommended to use a real certificate to avoid managing different certificates for different providers.

The certificates you will provide cannot be used in any way for a different consumer registration - even for testing/Sandbox purposes.

Finally, registration to additional providers - beyond the list of providers you will be setup for - during the onboarding procedure, will be considered outside of your initial setup and hence might be subject to additional setup fees.


Step 4: Open-up access to the API

Once you are registered with the respective providers and your access is set up, you are ready to begin using the LUXHUB One API. The access will start in Sandbox mode, i.e. accessing providers' PSD2 sandboxes, and, when you decide that you are satisfied with the level of testing of your application, it can be migrated to Production.

It is important to note that all considerations above related to your onboarding are environment specific, i.e. there is no necessary link between the onboarding of the consumer in the Sandbox and Production environments. As such, none of the artifacts required for onboarding should be considered a priori shared between environments.


C. Account Information Service (AIS)


LUXHUB One enables access, analysis and consolidation to an individual or SME's account data from their bank or other financial institution (e-money wallet provider for e.g.) with their explicit consent. This data could be a list of accounts, a specific account’s balance or the list of incoming and outgoing transactions on a specific account.

Popular services include account aggregation apps that group various online banking accounts under a single user interface, or real-time credit scoring based on cash account movements.

The PSD2 regulation requires that the access to account information is limited to information for which the end customer has issued the order and authorisation of, and which is required within the scope of the service to be performed.


1. End-user initiates an account information request. It is assumed that the end user is already logged into the consumer system.

2. Consumer shows the list of available providers (obtained from LUXHUB One) to the end-user. LUXHUB One will return only providers setup for your organisation out of all supported providers.

3. End-user chooses the provider to whom he wants to connect to recover account information.

4. Consumer presents a consent request capture page towards the end-user. Once the user confirms that he wants to authorize the consent, the consumer initiates a consent request for the respective provider. According to provider type, this might mean an additional request for establishing consent in the provider system - made transparently by LUXHUB One - or may take the end-user directly to the consent authorization page.

5. End-user performs the strong customer authentication (SCA) in the realm of the provider, thus granting authorization to LUXHUB One - and through it to the consumer - to access his account information.

6. Following the successful SCA, LUXHUB One receives an authorization code to be exchanged for the access/refresh tokens.

7. The PSD2 API provider issues an access/refresh tokens pair that will be used by LUXHUB One, identifying itself as consumer, for accessing the end-user accounts information.

8. LUXHUB One creates a consumer token, identifying the consumer, provider, end-user authorized relation - and provides it to the consumer. Each of the LUXHUB One API calls made by the consumer will have to use this token in a header in order to identify the resources to be accessed and also to show that access was authorized by the end-user. This token is bound - 1-to-1 - to an access token, as received from a provider.

9. The consumer makes a LUXHUB One API call to request a specific account information.

10. lUXHUB One extracts the necessary info from the consumer token that was sent, identifies the corresponding access token for the respective provider to which the request is addressed and forwards the call to the respective provider with the access token as authorization bearer token.

11. The provider verifies that the access to account information for the respective user is authorized and returns the relevant account information.

12. Account information is sent to the Consumer in the format specified by the LUXHUB One API. 


Additional information

Transactions older than 90 days

When LUXHUB One is requesting the consent for account information, it adds the scope for extended transaction history too. This way, when the end-user is authorizing the consent for AIS, it is also doing it for extended transaction history (the end-user will be warned about it during consent authorization at provider side). Some providers do not allow this and a second consent authorization is needed with extended transaction history scope. In this case, LUXHUB One will respond with a 302 (/accounts/{accountId}/transactions endpoint), including a Location header with the URL for the SCA to authorize the consent with extended transactions history scope for older than 90 days.


D. Payment Initiation Service (PIS)

In addition to account information related services, LUXHUB One enables you to initiate a payment order, with the account holder’s explicit consent, from their online payment account. LUXHUB One provides the option to leverage the different payment-related features of covered PSD2 APIs. For example, the API-initiated payment could be either a one-off transaction or a recurring one; it could concern a single transaction or multiple simultaneous transactions.



1. End-user starts a payment. It is assumed that the end user is already logged into the consumer’s system and that the user has already provided - or that you already have available - the payment details, such as the receiving account reference; the amount and currency, etc.

2. The consumer forwards the request to LUXHUB One.

3. If required, LUXHUB One obtains the access token from the provider - often through client credentials - and prepares the payment request with the required information, such as signature, authorization for the provider selected, etc. 

4. The payment initiation request is transformed to match the provider's initiate payment API specification and forwarded.

5. The provider sends back the response for the payment initiation request.

6. LUXHUB One checks if an SCA is required to authorize the payment and it forwards the URL to do so, together with the payment id and its status.

7. The end user authorizes the payment by performing the SCA.

8. Additionally, the consumer can initiate a request to get the payment status - but note, this operation is not supported by all providers.


E. Additional technical considerations


API access

Access to the LUXHUB One API is controlled at application level, via Oauth2 client credentials grant type during the onboarding process. Please see details about how this is implemented below.

Moreover, each consumer that is accessing the API will have to set specific HTTP headers in their requests, in order to access resources of a certain user held by a certain provider that are pertinent in identifying the provider and the user in question. Similarly, the request will also need to contain the permission request identifier, so the system will be able to identify that the user has indeed granted consent authorization via SCA.


End user authorisation

Users of a consumer's application will need to log in with their financial institutions - the provider - on order to grant explicit consent for your application to access their banking data. In most cases, this will involve redirecting users to their financial institution's authorisation screen. The user is redirected back to the consumer application via the URL that you have configured for your application when registering for One API - the consumer token (permission-id) will be used in a header for all the subsequent API calls.

For long-lived consent support - using the OAuth2 refresh token grant, an attempt will be made to refresh the associated access token when requesting financial data with an expired access token.


Security considerations

Consumer connection to the LUXHUB One API is secured via MTLS authentication at protocol layer, while the consumer is identified via credentials access token. Message integrity is insured via http-signature. On the providers' side, LUXHUB One connects via PSD2 APIs, so the regulatory compliance requirements of PSD2 must be followed, i.e. using eIDAS certificates for identification (QWAC) and message integrity (http-signing with QSEALC certificate), along with applicative authorization via OAuth2 protocol. User access authorization to its resources - accounts, balances, transactions history - is given using SCA, as part of OAuth2 Authorization Code Grant flow. The SCA procedure implemented by each provider needs to comply with the regulatory items published by the EBA for PSD2 compliance.


Considerations related to eIDAS Certificates

The eIDAS certificates referred to in this guide are X509 certificates with dedicated protection profiles that enables them to be used in the PSD2 context and are issued by Qualified Trusted Service Providers. To achieve PSD2 security requirements, banks and PSD2 service providers will use Qualified Certificates for Websites and Qualified Certificates for Electronic Seals. Those certificates will be issued by Qualified Trust Service Providers (QTSPs) based on the technical standard, ETSI TS 119 495, which was published in May 2018. Qualified Certificates enable identification and verification of the payment institution by a third party. Identification will be based on the legal name of an organization, registration number and its main role(s) in the payments space.

There are two types of such certificates:

·         QWAC (Qualified Website Authentication Certificate): used as Client Certificates in MA-TLS

·         QSeal (Qualified Certificate for Seals): used to sign requests using http-signature

PSD2 APIs might require usage of both types of certificates - QWAC to access the API and QSeal for http-signature, i.e. message signing. As such, it is strongly recommended to always provide a pair of QWAC/QSEALC certificates for onboarding and usage purposes.

LUXHUB will use the eIDAS certificates provided by each consumer to authenticate towards each respective provider onboarded.


Message Signing

All the requests sent by API consumers to LUXHUB One have to be signed at application level using the http-signature protocol as defined in the RFC draft. In the current version, LUXHUB One supports the asymmetric algorithm rsa-sha256.

The corresponding public key will be present as a header in all the requests made towards the API.

LUXHUB One's implementation of the http-signature is using RFC2253 for formatting the distinguished name of the CA that issued the certificate used for signing - as part of the keyId element of signature header.

For example, considering Java as an implementation language, and referring to the X500Principal class documentation, the correct code for implementing the keyId parameter should be:

public static String getKeyIdFromCertificate(String certificate) {
  X509Certificate cert = PublicKeyLoader.loadCertificate(certificate);
  String issuer = cert.getIssuerX500Principal().getName(X500Principal.RFC2253);
  String serialNumberHexadecimal = cert.getSerialNumber().toString(16);
  return String.format("SN=%s,CA=%s", serialNumberHexadecimal, issuer);

LUXHUB One does not require any particular header for the signature - the only restriction is that the header must be present in the API specification for the endpoint being called. But, as a recommendation, “x-request-id” and “date” headers should be used for signing messages. Note that only requests made by the consumer of the API must be signed and that responses sent back by LUXHUB One are not signed.


Message signing example

Below, you can find the details of an example of a signature calculated using the “x-request-id” and the “date” headers. Note that the date must be in the format “EEE, dd MMM YYYY HH:mm:ss GMT”, as indicated in the LUXHUB One API reference.


keyId="SN=0,CA=CN=Mock-eIDAS IntermediateCA,OU=PRD,O=LUXHUB SA,L=Strassen,ST=Luxembourg,C=LU",algorithm="rsa-sha256",headers="x-request-id date",signature="j+2WkoexL0y45uCCv3onOcrqfHgRgF2djnm/vHHqZro2IzFXgKwV2xqmrvYatFERfUySJt5tbYZ0L0/9gw7LSPPBZv27x5Vvcqu+ED52E2q5zWmivIuc42fiaMwfuyZis+mBPqEap6ZqFihbOlJVbhTxm67hcgppLAuBMvS1olBX3HIZOMhz4L1PXn3JJE2MRmxN1MJ5rMCyNPuMChr1gutiWO70UwC4wALTqOSnUfw83Zm+AhvaRkQ/AjhagpAI1PVTMNts0OtXeu5D38gZNsylWNg+jopPLuxxKbUDC1uYD1R0jME3/32PGw/5WPXhxBovK+IkNGXV5foLJEqg4A=="

Headers values:

Date: Tue, 21 Jan 2020 10:23:56 GMT
X-Request-ID: 8464a585-da8e-4b8b-b7c9-7a28de111a57
Additionally, the “TPP-Signature-Certificate” header must be present, containing the sender's public key associated to the private one used to sign the request.

Code Snippet:

Following code snippet (Java) is using tomitribe library for signing http requests:

import org.tomitribe.auth.signatures.Signature;
import org.tomitribe.auth.signatures.Signer;
public HttpSignature sign(Map<String, String> headers, String method, String uri, String payload, String keyId) {
    LOGGER.debug("Calculating signature of {} {}", method, uri);
    HttpSignature httpSignature = new HttpSignature(); 
    LOGGER.debug("Request headers: {}", headers);
    Map<String, String> headersToSign = headersToSign(headers, method, uri);
    LOGGER.debug("Headers to be signed: {}", headersToSign);   
    List<String> signatureHeaders = new ArrayList<String>();
    headersToSign.keySet().forEach(key -> signatureHeaders.add(key));
    Signature signature = new Signature(keyId, Constants.RSA_SHA256, null, signatureHeaders);
    PrivateKey privateKey = loadPrivateKey();
    Signer signer = new Signer(privateKey, signature);
    Signature signed = sign(method, uri, headersToSign, signer);
    setSignatureHeader(httpSignature, signed);
    LOGGER.debug("Calculated signature: {}", httpSignature);
    return httpSignature;   
protected void setSignatureHeader(HttpSignature httpSignature, Signature signed) {
    httpSignature.setSignature(signed.toString().replaceFirst("Signature ", ""));
private Signature sign(String method, String uri, Map<String, String> headersMap, Signer signer) {
    try {
      LOGGER.debug("Performing signature for method {}, uri {} and headers {}", method, uri, headersMap);
      return signer.sign(method, uri, headersMap);
    } catch (Exception e) {
      LOGGER.error("Error when siging the request.", e);
      throw new HttpSignatureException("Error when signing the request.", e);
protected Map<String, String> headersToSign(Map<String, String> headers, String method, String uri) {
    Map<String, String> headersToSign = new HashMap<String, String>();
    List<String> allowedHeaders = getAllowedHeadersToSign();
    LOGGER.debug("Allowed headers to sign: {}" , allowedHeaders);
    headers.entrySet().forEach(entry -> {
      if (!allowedHeaders.contains(entry.getKey())) {
      headersToSign.put(entry.getKey(), entry.getValue());
    return headersToSign;
protected abstract List<String> getAllowedHeadersToSign(); //returns the header names that are used in the signature. Ex: x-request-id date
protected abstract String getSignatureKey(); //returns the keyId as indicated at the beginning.
public class HttpSignature {
    private String digest;
    private String signature;
    private Map<String, String> extraHeaders = new HashMap<>();
    public String getDigest() {
      return digest;
    public void setDigest(String digest) {
      this.digest = digest;
    public String getSignature() {
      return signature;
    public void setSignature(String signature) {
      this.signature = signature;
    public Map<String, String> getExtraHeaders() {
      return extraHeaders;
    public void setExtraHeaders(Map<String, String> extraHeaders) {
      this.extraHeaders = extraHeaders;
    public String toString() {
      return ToStringBuilder.reflectionToString(this);

Calculate Digest

Digest header is used to verify the integrity of the message body that has been sent to the API. In the current version, LUXHUB One supports algorithm SHA-256 to calculate digest.

Following code snippet (Java) is using class to calculate Digest:

private static final String ALGORITHM = "SHA-256";

public byte[] calculateDigest(byte[] payload) {
   return ALGORITHM + "=" + MessageDigest.getInstance(ALGORITHM).digest(payload);

The final result must look like SHA-256=EzukVzoL09e7MJnGACZ/juc/BbirCjNBKrPkQKKQPGo=.


Definition of API breaking changes

In case of support or more information needed, please visit the Support page or get in touch with us directly. 


F. Changelog/versions


Version Publication date Changes
0.3.12 20.07.2020

- Internal improvement & fixes



- Internal improvement & fixes



- Internal improvement & fixes

0.3.9 08.06.2020

- New query parameters on Providers endpoint

0.3.8 14.04.2020

- Added support for detailed consent model

- Added support to recurring payments

0.3.7 27.03.2020

- Additional payment details for Providers endpoint

- Support for additional provider specific fields added

0.3.6 09.03.2020

- Multiple PSU support

- More consistent wording in relation to permissions



This website uses cookies. By continuing to use our website, you accept the use of these cookies.