Lloyds Banking Group (LBG) Open Banking Sandbox Developers Guide V1.7

1 Introduction

1.1 OVERVIEW

The Lloyds Banking Group (LBG) Sandbox is designed to replicate the functionality present in the LBG production environment. It is provided for the Third Party Providers (TPP) to be able to develop and test their APIs in a safe, controlled environment , without impacting the live environments.

This Sandbox enables TPPs to complete end-to-end testing of their products and allows them to use the same codebase when they move to the production environment.

The Sandbox, where possible and where appropriate, mirrors all the functionality of the production interface relating to Account Information Services (used by AISPs), Payment Initiation Services, including VRPs (used by PISPs), Confirmation of Funds Services (used by CBPIIs) , and Event Notifications delivered through Aggregated polling. There are, however, some key differences and this guide seeks to capture them.

This guide should be read in conjunction with the Technical Implementation Guide and the guide on How to Register using DCR , which are issued as part of the production environment.

1.2 KEY DIFFERENCES BETWEEN THE SANDBOX AND THE PRODUCTION INTERFACE

The functionality works like the production interface for all the happy paths and error scenarios. The exceptions to this are:

1.2.1 BRANDING

  • Functionally, the Sandbox is agnostic to the different brands of the Lloyds Banking Group (LBG) like Lloyds, Halifax, Bank of Scotland and MBNA.

  • The Sandbox UI is themed on a single common LBG brand unlike the production interface that are themed for the individual brands.

  • The Sandbox provides a set of eight inbuilt PSUs as a representative sample of the differences in the data across brands and channels.

    • Lloyds - Retail, Retail Business Banking (RBB), Commercial

    • Halifax – Retail

    • BoS - Retail, Retail Business Banking (RBB), Commercial

    • MBNA – Retail

1.2.2 MOCK DATA

  • Mock data includes the PSUs along with their accounts, transactions, balances, beneficiaries, direct debits, standing orders, scheduled payments and product.

  • There is no relationship between the mock data and any real-world user details or credentials.

1.2.3 TPP ONBOARDING

  • The TPPs must be registered to the Open Banking Sandbox directory (see Onboarding below), whereas, to access the production interface, TPPs must be registered with the Open Banking Production directory.

  • App registration can only be done using Dynamic Client Registration (DCR).

  • Only one app registration per software statement is possible.

  • LBG Sandbox only supports PS256 signed SSAs without any backward compatibility for RS256.

1.2.4 PSU CONSENT JOURNEY

  • TPPs are not required to be an LBG customer to use the Sandbox. Pre-defined PSU accounts have been established for TPP’s use as listed here .

    Journey Type User Name Password
    BoS Business bab001 Password123
    BoS Commercial bac001 Password123
    BoS Retail bar001 Password123
    Halifax Retail har001 Password123
    Lloyds Business llb001 Password123
    Lloyds Commercial llc001 Password123
    lloyds Retail llr001 Password123
    MBNA Retail mbr001 Password123
     
  • The Sandbox only supports Primary authentication.

  • The Sandbox does not support:

    • Step Up authentication

    • Two Factor authentication

    • App to App consent

    • Decoupled flows

1.2.5 PISP API - PAYMENT EXECUTION

  • Though the Sandbox supports the PISP APIs, the payment transactions will not affect the actual account balance of a PSU. Hence the account balance will not change over time, irrespective of the number of times the TPP invokes the payment APIs.

1.2.6 UNSUPPORTED FEATURES

  • Customer re-authorisation

  • Fraud checks

  • Daily limit checks

  • Developer portal is not available in Sandbox

1.2.7 STRESS TESTING

  • There is sufficient data capacity and performance to facilitate effective and realistic TPP testing. However, the Sandbox does not provide the capacity to replicate production volumes and hence cannot be used for stress/load testing.

1.2.8 API URL VERSIONING

  • The API URLs in the sandbox test facility will use Major.Minor.Patch versioning (e.g. 3.1.10), as opposed to 3.1 in Production. This is to allow the sandbox test facility to potentially support multiple patch versions and allow TPPs to test implementations against differences in functionality between minor versions (JWS between 3.1.2 and 3.1.10 for example)

  • The recommendation is to use the RS Discovery endpoint to obtain endpoint URLs (see section 2.4)

2. COMPLETING AN END-TO-END API JOURNEY

This section explains how to on-board onto the Lloyds Banking Group Sandbox, and how to complete an end-to-end API journey. In this instance, the example used is an Account Information API journey.

2.1 ON-BOARDING ONTO THE SANDBOX

2.1.1 FIRST TIME USERS

2.1.2 PRE-REQUISITES FOR REGISTERING APPLICATIONS IN THE SANDBOX

  • Certificate Signing Request (CSR) and private keys for transport and signing.

    • TPPs should use their own key generation tool and management policies and must create the CSRs and the private keys, each for transport and signing.

  • Software Statement Assertion (SSA) to identify the TPP’s Open Banking application.

    • Navigate to the organization summary page on the Open Banking Sandbox Directory

    • Click ‘Add new Software Statement’ under ‘Software Statements’ tab.

    • Complete ‘Add new Software Statement form’

    • Click ‘Add new Organisation Certificate’ under ‘Certificates’ tab and upload the OB Seal and OB Wac CSRs and keep note of the KID

    • Check if the new Software Statement creation has been completed.

    • Generate the Software Statement Assertion (SSA) and copy to clipboard for future use in on-boarding.

  • Digital certificates(PEM files) required for transport and signing.

    • Under the “Software Statements” tab, once you select the Software statement that was created, there is a section “Keys/certificates” where you can find all the associated certificates. Once you locate your certificates using KID, by using the three dot menu besides it, you get an option saying “Get PEM” which gives you the link to download the PEM file.

       

    • You can also go to the “Certificates” tab directly and locate your KID and use the “Get PEM” button besides it to get the PEM files.

       

    • Alternatively, you can decrypt the SSA using tools like https://jwt.io/ and get the “software_jwks_endpoint”. Visit this “software_jwks_endpoint” link, locate the releavent entry using the KID and download the PEM files for transport and signing.

       

2.1.3 REGISTER AN APPLICATION WITH LBG SANDBOX

Once you are registered on the Open Banking Sandbox Directory you can access the LBG Sandbox:

  • To use the Sandbox APIs, TPPs must have an application identified by an SSA which is used to get the Client ID and Client Secret (to identify who is calling the APIs).

  • In order to create a new application, TPP must use Dynamic Client Registration (DCR). The DCR call should be made to the registration endpoint described in the well-known endpoint. This document should be read in conjunction with the Production guide: How to Register using DCR

  • When creating a new application using DCR, the redirect URI will be picked up from “software_redirect_uris" mentioned in the request object (this should match the redirect URI in the SSAwhich was created above).

  • The application is automatically subscribed to all the available APIs depending on the “roles” (e.g. accounts, payments, fundsconfirmations) available in the request object(RO) which should be a subset of software_roles in the SSA (e.g. AISP, PISP, CBPII).

Once the application is created successfully, the TPP will get back the client_idin the DCR API response

2.1.4 SELECTING PSU CREDENTIALS

  • After logging into the Sandbox, TPPs will see a PSU Page link in the header navigation that will take them to the Lloyds Banking Group (LBG) branded PSU credential information page.

  • This page will have a title and introduction text, followed by the PSU credentials.

  • The PSU credential information will include usernames for all available LBG brands and channels.

  • The password is the same for all the PSUs.

  • This page will remain accessible to TPPs for future reference.

2.2 LIST OF APIS AVAILABLE FOR TESTING

The following list of APIs are in scope for testing

AISP

Service Endpoints METHOD V3.1.<X>
Accounts /accounts GET Yes
Accounts /accounts/{AccountId} GET Yes
Accounts /account-access-consents POST Yes
Accounts /account-access-consents/{ConsentId} GET Yes
Accounts /account-access-consents/{ConsentId} DELETE Yes
Balances /accounts/{AccountId}/balances GET Yes
Transactions /accounts/{AccountId}/transactions GET Yes
Beneficiaries /accounts/{AccountId}/beneficiaries GET Yes
Direct Debits /accounts/{AccountId}/direct-debits GET Yes
Standing Orders /accounts/{AccountId}/standing-orders GET Yes
Products /accounts/{AccountId}/product GET Yes
Offers /accounts/{AccountId}/offers GET Yes
Statements /accounts/{AccountId}/statements GET Yes
Statements /accounts/{AccountId}/statements/{StatementId}/file GET Yes
Scheduled Payments /accounts/{AccountId}/scheduled-payments GET Yes
Parties /party GET Yes
Parties /accounts/{AccountId}/party GET Yes
Parties /accounts/{AccountId}/parties GET Yes
 

CBPII

Service Endpoints METHOD V3.1.<X>
Confirmation of Funds /funds-confirmation POST Yes
Confirmation of Funds /funds-confirmations-consents POST Yes
Confirmation of Funds /funds-confirmation-consents/{ConsentId} GET Yes
Confirmation of Funds /funds-confirmation-consents/{ConsentId} DELETE Yes
 

PISP

Service Endpoints METHOD V3.1.<X>
Domestic Payments /domestic-payment-consents POST Yes
Domestic Payments /domestic-payment-consents/{ConsentId} GET Yes
Domestic Payments /domestic-payment-consents/{ConsentId}/funds-confirmation GET Yes
Domestic Payments /domestic-payments POST Yes
Domestic Payments /domestic-payments/{DomesticPaymentId} GET Yes
Domestic Scheduled Payments /domestic-scheduled-payment-consents POST Yes
Domestic Scheduled Payments domestic-scheduled-payment-consents/{ConsentId} GET Yes
Domestic Scheduled Payments /domestic-scheduled-payments POST Yes
Domestic Scheduled Payments domestic-scheduled-payments/{DomesticScheduledPaymentId} GET Yes
Domestic Standing Orders /domestic-standing-order-consents POST Yes
Domestic Standing Orders /domestic-standing-order-consents/{ConsentId} GET Yes
Domestic Standing Orders /domestic-standing-orders POST Yes
Domestic Standing Orders domestic-standing-orders/{DomesticStandingOrderId} GET Yes
International Payments /international-payment-consents POST Yes
International Payments /international-payment-consents/{ConsentId} GET Yes
International Payments /international-payment-consents/{ConsentId}/funds-confirmation GET Yes
International Payments /international-payments POST Yes
International Payments /international-payments/{InternationalPaymentId} GET Yes
File Payments /file-payment-consents POST Yes
File Payments /file-payment-consents/{ConsentId} GET Yes
File Payments /file-payment-consents/{ConsentId}/file POST Yes
File Payments /file-payment-consents/{ConsentId}/file GET Yes
File Payments /file-payments POST Yes
File Payments /file-payments/{FilePaymentId} GET Yes
 

International Scheduled Payment and International Standing Order APIs are not available.

VRP

Service Endpoints METHOD V3.1.<X>
Domestic VRP / domestic-vrp-consents POST Yes
Domestic VRP / domestic-vrp-consents/{ConsentId} GET Yes
Domestic VRP / domestic-vrp-consents/{ConsentId} DELETE Yes
Domestic VRP / domestic-vrp-consents/{ConsentId}/funds-confirmation POST Yes
Domestic VRP / domestic-vrps POST Yes
Domestic VRP / domestic-vrps/{DomesticVRPId} GET Yes
 

Event Notifications

Service Endpoints METHOD V3.1.<X>
Aggregated Event Polling /events POST Yes
 

2.4 OTHER USEFUL INFORMATION

  1. LBG Sandbox APIs are behind the following domains – these are over MA-TLS – hence the TPPs should present their OB-signed client cert against these domains to validate if the SSL handshake is working as expected (e.g. by using an appropriate openSSL command, in chrome etc.)

    https://matls.as.aspsp.sandbox.lloydsbanking.com/open-banking/mtlsTest
    https://matls.as.aspsp.sandbox.lloydsbanking.com:443/open-banking/mtlsTest
    https://matls.rs.aspsp.sandbox.lloydsbanking.com/open-banking/mtlsTest
    https://matls.rs.aspsp.sandbox.lloydsbanking.com:443/open-banking/mtlsTest

  2. Discovery Endpoints

    1. API discovery

      https://rs.aspsp.sandbox.lloydsbanking.com/open-banking/discovery

    2. Well-known endpoint

      https://as.aspsp.sandbox.lloydsbanking.com/oauth2/.well-known/openid-configuration

  3. We support OIDC Hybrid Flow.

  4. All APIs are secured with TLS Mutual Authentication where Certs are signed by Open Banking CA.

  5. The DCR call should be made to the registration endpoint described in the AS well-known endpoint (above)

    Registration endpoint https://matls.as.aspsp.sandbox.lloydsbanking.com/open-banking/register/

    This document should be read in conjunction with the Production guide: How to Register using DCR

  6. The authorise url journey in the browser uses Open Banking signed certificates. Hence the Open Banking Sandbox root and issuer certificates should be added to the trust store to avoid untrusted certificate issues in the browser. The Open Banking sandbox root and issuer certificates are available for download from the Open Banking confluence page

2.5 TESTING THE ACCOUNT INFORMATION APIS

2.5.1 SETUP CLIENT CREDENTIALS TOKEN

 

In this step, the AISP obtains an Access Token using the “client_credentials” grant type. When an Access Token expires, you will need to re-request for another Access Token.

  • curl -X POST \

    --key <TRANSPORT_PRIVATE_KEY_FILE> \

    --cert <TRANSPORT_PEM_FILE> \

    https://matls.as.aspsp.sandbox.lloydsbanking.com/oauth2/access_token

    -H 'Content-Type: application/x-www-form-urlencoded' \

    -H 'cache-control: no-cache' \

    -d 'grant_type=client_credentials&scope=accounts&client_id=<CLIENT_ID>'

Data

Parameter: grant_type

Example Value:

client_credentials

Description:

The grant type being requested

Parameter: scope

Example Value:

accounts

Description:

The scope being requested.

Parameter: client_id

Example Value:

f5fe8446-5fc2-42f5-bd4…….

Description:

Client Id obtained during onboarding

Note down the “access_token” in the response for further use.

2.5.2 INVOKE THE ACCOUNT REQUEST API

Using the Access Token obtained in the previous step, invoke the Accounts Consent API with the desired permissions in the request body.

curl -X POST \

--key <TRANSPORT_PRIVATE_KEY_FILE> \

--cert <TRANSPORT_PEM_FILE> \

https://matls.rs.aspsp.sandbox.lloydsbanking.com/open-banking/v3.1.6/aisp/account-access-consents \ <Value of ‘URL’ from the API Discovery Endpoint >

-H 'Accept: application/json' \

-H 'Authorization: Bearer <ACCESS_TOKEN_FROM_THE_PREVIOUS_STEP>' \

-H 'Content-Type: application/json' \

-H 'cache-control: no-cache' \

-H 'x-fapi-financial-id: <Value of ‘FinancialId’ from the API Discovery Endpoint >' \

-d '{

"Data": { "Permissions": [

                       LBG Sandbox User Guide            

"ReadAccountsDetail", "ReadBalances"

]

},

"Risk": {}

}'

Headers

Parameter: authorization

Example Value:

Bearer AAIkMDM5NDJmZTUtOGNiMi00N zVmLWIwMTItNDgyZjM0ZTE...

Description:

The “access_token” obtained in the previous step.

Body

Parameter: Data

Example Value:

{

"Data": { "Permissions": [

"ReadAccountsDetail", "ReadBalances"

]

},

"Risk": {}

}

Description:

The permissions being requested.

Please refer here for a full list of the allowed permissions.

Note down the AccountRequestID or ConsentId in the response data. This is required in the next step to be used in the claims body.

2.5.3 AUTHORISE CONSENT – HYBRID FLOW

In this step, create the authorization request (using a signed JWT request containing the AccountRequestId or ConsentId as a claim) for the customer to consent to the account consent request.

Using a web browser, invoke the URL below to emulate the customer giving consent after changing the parameterized values as required.

https://as.aspsp.sandbox.lloydsbanking.com:443/oauth2/authorize?response...<CLIENT_ID_FROM_THE_FIRST_STEP>&state=<STATE>& nonce=<NONCE>&scope=openid%20accounts&redirect_uri=<REDIRECT_URI_USED_DURIN G_ONBOARDING>&request=<SIGNED_CLAIMS_IN_BASE64>

URL Parameters

Parameter: response_type

Example Value:

code id_token

Description:

The OAuth flow type being used

Parameter: client_id

Example Value:

10d260bf-a7d9-444a-92d9- 7b7a5f088208

Description:

The client ID of your application registered in the Sandbox

Parameter: State

Example Value:

12345

Description:

The state as specified by the TPP

 
Parameter: Scope

Example Value:

openid accounts

Description:

The scope being requested.

Parameter: redirect_uri

Example Value:

https://example.com/redirect

Description:

The redirect URL of the application registered in the Sandbox

Parameter: Nonce

Example Value:

4987594875485-j

Description:

The nonce as specified by the TPP

Parameter: request

Example Value:

eyJhbGciOiJSUzI1NiIsImtpZCI6Ikd4bElpd2lhblZxc0R1dX
NoZ2pFME9UVXhPVGsifQ.eyJpc3MiOiJodHRwczovL2FwaS5hb
HBoYWJhbmsuY29tIiwiYXVkIjoiczZCaGRSa3F0MyIsInJlc3B
vbnNlX3R5cGUiOi…..

Description:

This is an OIDC request object containing a claim (sample given below) identifying the accounts that needs to be authorised. Please ensure it is signed using the signing kid, signing private key and the PS256 algorithm. To modify it to support your test scenario use the debugger at https://jwt.io/

 

A sample claims body syntax that may be used for signing (Replace <xxxx> values with actuals):

                
                {
                  "sub": "urn-example-bank",
                  "exp": <EXPIRY_IN_SECONDS_SINCE_EPOCH>,
                  "iat": <ISSUED_AT_IN_SECONDS_SINCE_EPOCH>,
                  "iss": "<CLIENT_ID_FROM_THE_FIRST_STEP>",
                  "aud": "<Value of the issuer in the> well-known endpoint>", 
                  "response_type": "code id_token",
                  "client_id": "<CLIENT_ID_FROM_THE_FIRST_STEP>",
                  "redirect_uri": "<REDIRECT_URI_USED_DURING_ONBOARDING>",
                  "scope": "openid accounts",
                  "state": "<STATE>",
                  "nonce": "<NONCE>",
                  "claims": {
                    "userinfo": {
                      "openbanking_intent_id": {
                        "value": "<ACCOUNT_REQ_ID_OR_CONSENT_ID>",
                        "essential": true
                      }
                    },
                    "id_token": {
                      "openbanking_intent_id": {
                        "value": "<ACCOUNT_REQ_ID_OR_CONSENT_ID>",
                          "essential": true
                      },
                      "acr": {
                        "value": "urn:openbanking:psd2:sca",
                        "essential": true
                      }
                    }
                  }
                }      
              
            

Follow the UI flow using the credentials of any of the static PSU user accounts supplied with the Sandbox as described under section 2.1.4

If there were untrusted certificate issues when the authorize url was launched in the browser, ensure instructions under section 2.4(6) is completed.

At the end of the flow, take note of the authorization “code” and id token appended to the URL

e.g.https://example.com/redirect?code= xxxxxxxxxxxxx&id_token=xxxxxxxxxx

2.5.4 GET THE ACCESS TOKEN REQUIRED TO ACCESS THE ACCOUNT

Following the OAuth2.0 protocol, exchange the access code for the access token required in the next step, using the “authorization_code” grant type.

Once the below call is made, you will get access token along with refresh token. This refresh token can be in turn used for procuring new access token when it expires.

curl -X POST \

--key <TRANSPORT_PRIVATE_KEY_FILE> \

--cert <TRANSPORT_PEM_FILE> \

https://matls.as.aspsp.sandbox.lloydsbanking.com/oauth2/access_token

-H 'Content-Type: application/x-www-form-urlencoded' \

-H 'cache-control: no-cache' \

-d 'grant_type=authorization_code&code=<CODE_FROM_THE_PREVIOUS_STEP>&redirect_ uri=<REDIRECT_URI_USED_DURING_ONBOARDING>&client_id=<CLIENT_ID>'

Body

Parameter: grant_type

Example Value:

authorisation_code

Description:

The grant type being requested

Parameter: redirect_uri

Example Value:

https://example.com/redirect

Description:

The redirect URL which must match that of the application registered in the Sandbox.

Parameter: code

Example Value:

21a0ff30-3adb-423a…..

Description:

The authorisation code retrieved in step 3

Parameter: client_id

Example Value:

f5fe8446-5fc2-42f5-bd4…….

Description:

Client Id obtained during onboarding

Take note of the “access_token” in the response data for further use.

2.5.5 GET ACCOUNTS

You can use the Access Token to retrieve data using the AISP APIs.

The following example is from the Account API v3.1.10 Specification.

Where the initial Access Token expires, you must obtain a new Access Token using refresh token.

curl -X GET \

--key <TRANSPORT_PRIVATE_KEY_FILE> \

--cert <TRANSPORT_PEM_FILE> \

https://matls.rs.aspsp.sandbox.lloydsbanking.com/open- banking/v3.1.6/aisp/accounts ><Value of ‘URL’ from the API Discovery Endpoint>

-H 'Accept: application/json' \

-H 'Authorization: Bearer <ACCESS_TOKEN_FROM_THE_PREVIOUS_STEP>' \

-H 'Content-Type: application/json' \

-H 'cache-control: no-cache' \

-H 'x-fapi-financial-id: <Value of ‘FinancialId’ from the API Discovery Endpoint >'\

-H 'x-idempotency-key: <IDEMPOTENCY_KEY>'

Headers

Parameter: authorization

Example Value:

Bearer xyzAbcDef…

Description:

The “access_token” obtained in the previous step