Skip to content
Developerhome

Bank feeds onboarding API

  Less than to read

:

Onboarding through the UI is the preferred integration method. This is because we have already handled the complexity of the onboarding flow for different connections. It also reduces the need for future maintenance when there are brand or logo changes. These are managed centrally by the Sage Network Platform team

This guide walks through the development requirements for a product integrating directly with bank feeds through the exposed endpoints. Before integrating with the Banking Service user interface, integrate with the Authentication Service.

We consider a bank either direct, or indirect. This status determines how a user sets up their account.

Direct banks

Direct banks are where users send requests to their bank so Banking Service can retrieve their transactions. This typically involves Banking Service producing a PDF authorisation form. The user then sends this to the bank for the feed to start. Lloyds and RBS in the UK are examples of direct banks.

Indirect banks

The majority of bank feeds in Banking Service are indirect banks. Indirect refers to a mechanism where we take users through a UI flow to authorise and onboard bank accounts. The data sources for indirect banks can be:

  • 3rd-party aggregator services such as Yodlee, Plaid or SISS. Who may in turn use a bank’s API or screen-scraping to source transaction data.
  • Another category we call ‘Generic’. Here, onboarding is delegated through the Provider API to the data source.

API flow diagram

Flow diagram displaying the onboarding flow


Step 1. Get list of banks

The 1st step of integrating into bank feeds and onboarding a customer’s account is to identify the bank for their accounts. Call the GET banks endpoint to list all available banks. It can also be used to add filters to search on specific fields such as bank name or ‘top banks’. Specify the bank identifier as shown to specific bank details.

GET /banks/{bankId}

Consumer APIProduct -> Banking Service

Headers Description
x-application This is your application identifier which is generated from the Authentication Service.

Response

  {
      "name": "Chase",
      "primaryCountry": "USA",
      "primaryCountry2CharIso": "US",
      "authorisationMechanism": null,
      "accountTypes": [],
      "status": "supported",
      "authorisationData": null,
      "offBoardingMechanism": {
          "type": "none",
          "instructions": ""
      },
      "supportiframe": true,
      "popularBank": false,
      "bankURL": "https://www.chase.com",
      "flags": {
          "oauth": false
      },
      "dataProvider": "indirect",
      "capabilities": {
          "manualRefresh": false
      },
      "logo": "https://s3-eu-west-1.amazonaws.com/bnkc-dev01-s3-eu-west-1-banklogos/chase.png",
      "logoSvg": "https://s3-eu-west-1.amazonaws.com/bnkc-dev01-s3-eu-west-1-banklogos/chase.svg",
      "icon": "https://s3-eu-west-1.amazonaws.com/bnkc-dev01-s3-eu-west-1-banklogos/chase_icon.svg",
      "bankId": "fd105b12-887b-4277-95ea-157a41d0651e"
  }
:

Note: If a user’s bank is not available, they can request their bank be added using the POST /banksuggestions endpoint.


Step 2. Obtain an access token

Before integrating with the Banking Service, integrate with the Authentication Service.

To work with Banking Service, you need an access token (JWT) from Authentication Service. The JWT is generated using the unique IDs of the organisation (organisationId) and company (companyId). This JWT can be provided as a bearer token for Banking Service requests through the authorisation header: ‘Bearer ‘.


Step 3. Retrieve HTML – for indirect banks

GET /indirectlinkaccount

Consumer APIProduct -> Banking Service

Headers Description
x-application This is your application identifier which is generated from the Authentication Service.
Authorization This is the bearer token returned from your request to the /accesstoken endpoint as described in step 1.
Content-Type This should be set as application/json.

Query Parameters Description
bankid This is the identifier of the user’s bank which can be located in the Get Banks endpoint.
web Identify the route you will take to obtain request results. Can be true, false, or none.
callback Provide a callback if web = true. This is optional.
e2e Can be used to track a specific onboarding. This value is included when publishing a BankAccountCreated event to DataMesh. This is optional.

Response

  {
  "redirect":"{URL}",
  "pollRoute":"{URL}",
  "pollPeriod":5000
  }
Web parameter types
  • web = true: Returns a polling URL route. This can be used to monitor progress of the UI flow and obtain the final result.
  • web = true and callback: The client browser will redirect to the URL providing the bank account identifiers in the query string. For security reasons, the callback needs to be a value we have setup in our allowlist.
  • none: The product is assumed to be a desktop product using a desktop browser window. This window will receive a scripting event to capture the details.

Step 4. Open edirect – for indirect banks

Open the redirect URL. Users can then authorise their connection with the bank or aggregator.


Step 5. Poll for response – for indirect banks

When you’ve directed the user to the redirect URL returned in the GET /indirectlinkaccount, poll the poll route provided. This is a signed URL and can only be used 1 time.

GET /{pollRoute}

Consumer APIProduct -> Banking Service

200 Response

If the user has linked their account with the aggregator and we have the account information, we’ll return 200 with that account information (accountName, accountIdentifier and accountKey).You’ll need this for the POST bankAccount. If the user has been unable to link their bank account, we’ll return 200. However, the account will be null and success will be false.

  {
    "account" : {
      "accountName": "accountName",
      "accountKey": "accountKey",
      "accountIdentifier": "accountIdentifier" 
    },
    "success": true
  }

202 response

If the user has not completed linking their account, we’ll return 202 and the body will include a new pollRoute and pollPeriod. The next call to check the status should be done after a timeout of the pollPeriod – repeat this until you get the 200 response.


Step 5. Post bank account

When you’ve got the required account information, complete the POST /bankAccount request. You’ll need to capture the ‘requestedStartDate’ for transactions from the user first. We’ll attempt to get transactions from the aggregator from this date.

POST /bankaccounts

Consumer APIProduct -> Banking Service

Request body

{
  "accountType":"DEBIT",
  "accountName":"Plaid Checking (****0000)",
  "accountKey":"public-sandbox-2a4d8aae-d847-4276-8ce9-60d630cb25bc",
  "accountIdentifier":"XyJGMe6rpZfmowzN7ozAiz93dxMdbwuPoNW6B",
  "bankIdentifier":null,
  "branchIdentifier":"Newcastle",
  "defaultCurrency":"GBP",
  "bankId":"35188871-fdb4-4fbd-a7f1-b87e02e2aefa",
  "requestedStartDate":"2017-06-30T00:00:00.000Z"
}

201 response

{
    "bankId": "35188871-fdb4-4fbd-a7f1-b87e02e2aefa",
    "users": [],
    "bankIdentifier": null,
    "accountIdentifier": "XyJGMe6rpZfmowzN7ozAiz93dxMdbwuPoNW6B",
    "accountType": "DEBIT",
    "branchIdentifier": "Newcastle",
    "accountKey": "public-sandbox-2a4d8aae-d847-4276-8ce9-60d630cb25bc",
    "defaultCurrency": "GBP",
    "accountName": "Plaid Checking (****0000)",
    "statusReason": "standardAuthentication",
    "statusReasonModifiedDate": null,
    "dataProvider": "indirect",
    "authAlwaysRequired": false,
    "aggregatorId": null,
    "aggregatorName": "plaid",
    "requestedStartDate": "2017-06-30T11:30:00.000Z",
    "company": {
        "companyId": "5e778fe9-89d2-44b2-9348-64ed1d3d7ac3",
        "companyName": "TestCompany",
        "vatNumber": "123456789"
    },
    "accountant": {
        "accountantManaged": "none",
        "accountantCompanyId": null
    },
    "heldTransactions": 0,
    "clientAuthorisationToken": null,
    "status": "pending",
    "statusModifiedDate": "2023-02-27T11:14:37.062Z",
    "accountTypes": {},
    "feedSource": "automatic",
    "providerError": {
        "code": null,
        "message": null,
        "date": null
    },
    "ledgerBalanceAmount": 0,
    "ledgerBalanceDate": "2023-02-27T11:14:37.062Z",
    "availableBalanceAmount": 0,
    "availableBalanceDate": "2023-02-27T11:14:37.062Z",
    "lastTransactionsReceived": null,
    "lastUpdatedByProvider": null,
    "firstTransactionDate": null,
    "lastTransactionDate": null,
    "firstTransactionsReceived": null,
    "featureOptions": {
        "disableRuleWildcards": false,
        "autoCreateRules": false,
        "applyTransactionNarrativeMatching": false,
        "isPlaceholder": false,
        "allowCorrections": false,
        "allowMultiAccountLinking": true,
        "disableAutomaticRefresh": false,
        "allowManualUpload": false
    },
    "capabilities": {
        "manualRefresh": false
    },
    "bankAccountId": "6a842d59-b4f1-4496-8fc3-3471f2a3ce80"
}

Step 6. Get bank account

When you’ve posted a bank account it’ll be in a state of pending, it’ll only be set to active when Banking Service has authorised with the bank and recieved the first set of transactions. You can call the Get /bankaccounts endpoint using the bankAccountId of the account to check the status.

GET /bankaccounts/{bankAccountId}

Consumer APIProduct -> Banking Service

Headers Description
x-application This is your application identifier which is generated from the Authentication Service.
Authorization This is the bearer token returned from your request to the /accesstoken endpoint as described in step 1.
Content-Type This should be set as application/json.

Recap

In this walkthrough we’ve gone through the process of integrating directly with the bank feeds functionality for onboarding through the endpoints available on the Banking Service Consumer API.


What’s next?

When the account is in an active state you can begin to pull transactions into the product. Find out more about getting transactions.


Was this helpful?