Skip to content

Posting statements

  Less than to read

This walkthrough covers how to use the statements flow to upload transaction data to Banking Service through the Provider API. In this guide we will walk through the API calls made to and from Banking Service from your application and consuming product to demonstrate the posting statements flow detailed in our Postman collection.


  1. Statements are uploaded individually for each bank account.
  2. While multiple bank accounts can be processed simultaneously, only one statement from each account can be processed at the same time. Providers should loop through all transactions they want to send for a given account. Sending a single batch and then polling for its completion before sending the next.
  3. Bank accounts will remain in a ‘pending’ status until the first transactions have been posted by the provider.

API flow diagram

Flow diagram displaying the authorisation flow

Participant description
  • Product The Sage product which is currently integrated with Banking Service UI using Consumer API.
  • UI The user interface which allows the Sage user to search for a bank and allows them to authenticate.
  • Banking Service Banking Service handles the calls from the consuming API which Sage products use to interact with Banking Service. Also handling the provider API which handles the connection from any 3rd party provider.
  • Sage ID Sage ID is used to secure all requests into the Provider API. You will use Sage ID to obtain your access token.
  • Provider This refers to the 3rd party who is integrating with Banking Service. This 3rd party connector will need to contain the connector API endpoints to be able to handle the Banking Service flows and recieve data.

1. Get an access token

Using the Provider API to complete requests requires a Sage ID bearer token and an API key to authenticate the call.

An API key will be provided to you by Sage through the setup proccess. To Generate a Sage ID bearer token you can make a POST request to the token endpoint as detailed below. This token generally lasts 480 minutes but should be refreshed when receiving a 401 Unauthenticated responses from the API.

POST /oauth/token

Sage IDProvider -> Sage ID

This request should be sent with the following body:

Body Params Description
grant_type This should be set as client_credentails.
client_id This value identifies your client, and is tied to your provider; only tokens generated with your clientId can access resources associated with your provider.
client_Secret This value is required in order to generate Sage ID tokens. It should be handled as a secret and not shared.
audience This value identifies the Provider API and ensures that generated SageId tokens are targeted at the correct API.

These resources (keys) will be supplied by Sage.

2. Push transactions

The /statements POST endpoint is used to initialise processing of data for a single BankAccount. The body of the request can include up to 1,000 TransactionDetails objects, along with a single AccountDetails object. Some initial data validation checks will be performed; but full processing of the payload will happen asynchronously.

Transactions should be sent in the same order as they appear on the account statement. This means you should post the first 1,000 statements in date order and wait until this has been successful until moving onto the next 1,000. If an error occurs on this first POST, you would need to retry and confirm the status has been successful before moving on.

Processing progress can be tracked using the /statements/{statementId} GET endpoint.


Note: Any given BankAccount can only have a single statement in flight at any given time. This is to avoid any concurrency issues with the submission and validation of the data. This means a provider must wait for the response from the first request before making a second request for that BankAccount.


Note: When onboarding the user selects their requested start date which is sent to the provider within the bank account created notification. The provider should use this as the start date of transactions sent into the Banking Service for this account.

When TransactionDetails are sent, the AccountDetail balances must represent the account balances after these transactions are applied. The status and balances can be updated independent of TransactionDetails by sending 0 TransactionDetails objects.

POST /statements

Provider APIProvider -> Banking Service
Headers Description
x-api-key This value required in validating calls to the Provider API. It should be handled as a secret and not shared. Individual keys of the API may be throttled depending on usage agreements.
Authorization This is the value returned from your call to the /oauth/token endpoint.
Content-Type This should be set as application/json.

Descriptions of request body identifiers:

  • bankId - The identifier of the bank which this statement is for.
  • principalId – This is the unique identifier as it appears in Banking Service for the bank account this statement is for.
  • uniqueId – This is a unique identifier of this transaction. This uniqueId should never match another transaction and, if this transaction were to be posted again for any reason, the uniqueId MUST be the same.

Example request body:

    "data": {
        "bankId" : "29e94a6d-215e-4f9d-b207-83be8f7d845d",
        "accountDetails": [{
            "bankAccountId": "92c7bce5-3c01-4899-ab77-a5ecf85d6ff8",
            "status": "active",
            "ledgerBalance": 0,
            "availableBalance": 0,
        "transactionDetails": [{
            "uniqueId": "1",
            "bankAccountId": "92c7bce5-3c01-4899-ab77-a5ecf85d6ff8",
            "transactionAmount": 111,
            "transactionType": "CREDIT",
            "transactionStatus": "posted",
            "datePosted": "2019-11-02T23:00:12.000Z",
            "dateUserInitiated": "2019-11-04T22:54:00.000Z",
            "exchangeCurrency": "EUR",
            "exchangeAmount": 120,
            "checkNumber": "123456",
            "referenceNumber": "00000001",
            "description": "test_description",
            "payee": {
                "payeeDescription": "100001",
                "address1": "1 the something",
                "address2": "on some street",
                "address3": "on some estate",
                "city": "in a city",
                "state": "in a state",
                "postalCode": "MY POST CODE",
                "country": "GBR",
                "phoneNumber": "0091299291212",
                "payeeBankId": "123456",
                "payeeAccountId": "654321"
            "coordinates": {
                "lat": 0.9812,
                "long": 1.0238
            "narrative1": "narrative data",
            "narrative2": "extended narrative data",
            "category": {
                "topLevelCategory": "TopCategory",
                "subCategory": "SubCategory",  
                "categoryId": 12,
                "standardIndustrialCode": "9089"
             "expected": {
              "transactionDetailsCount": 1,
              "accountDetailsCount": 1,
              "transactionDebitSum": 0

3. Poll until succeeded

After posting your transactions through the POST /statements endpoint. You should check to ensure the transactions have succesfully been processed. This can be done by continuing to poll the GET /statements request using the statement ID returned from the previous call to POST /statements. In the response to this GET request you will find the status property. This can be used to identify the current processing state.

If the status is set to succeeded the processing is complete and the consuming Sage product will be able to retrieve these transactions. If it’s set to processing the service is in the middle of handling this request. This may be down to being busy or handling a large number of transactions.

The following are the possible returned status results when attempting to push your transactions:

  • accepting: Banking Service is accepting accountDetail and transactionDetail parts. The delete statement endpoint can be called by the provider.
  • queued: The transaction post request is queued for processing, and can no longer accept parts.
  • processing: The batch is being processed.
  • succeeded: The batch was processed successfully with no errors (may still contain warnings).
  • failed: The batch failed to process successfully and has errors. The delete statement endpoint should be called by the provider.
  • deleted: The batch has been deleted by the provider.

GET /statements

Provider APIProvider -> Banking Service
Headers Description
x-api-key This value required in validating calls to the Provider API. It should be handled as a secret and not shared. Individual keys of the API may be throttled depending on usage agreements.
Authorization This is the value returned from your call to the /oauth/token endpoint.
Content-Type This should be set as application/json.

Example response:

    "data": {
        "principalId": "fe5538b6-5570-4e67-8dde-f5ff5f2f4373",
        "expected": {
            "transactionDetailsCount": 1,
            "accountDetailsCount": 1,
            "transactionCreditSum": 111,
            "transactionDebitSum": 0
        "actual": {
            "transactionDetailsCount": 1,
            "accountDetailsCount": 1,
            "transactionCreditSum": 111,
            "transactionDebitSum": 0
        "status": "queued",
        "statusReason": "This Batch is queued for processing",
        "statusModifiedDate": "2019-11-27T07:55:34.021Z",
        "providerId": "fe5538b6-5570-4e67-8dde-f5ff5f2f4373",
        "_id": "d578ace1-920a-4988-9698-47e51ba3591e"
    "links": {
        "self": ""
    "meta": null,
    "error": null

The consuming Sage product can then make a request to the GET /transactions endpoint, allowing the customer to access these new transactions.


Note: The time transactions take to show up within the UI depends on the consuming product. Each products determines how they wish to download transactions retrieve the transactions, this can either be on a schedule, when the user logs in, when a user manually selects to download the latest transactions or a combination of all three. We are unable to specify how long it would take for each product.

Test Posting statements

Test description Expected outcome
A customer needs to be able to retrieve transactions. After your service posts statements through the provider API POST /statements endpoint, they should be available to the consuming product through the consumer API GET /transactions call.
You should not be able to post the same set of transactions twice. When a transaction status returns as ‘failed’ with details code ‘DuplicateTransaction’, you should handle this and only send transactions which have not previously been provided.


This walkthrough has covered the Banking Service flow for posting transactions. Covering how the provider can push transaction data into Banking Service through the /statements endpoint, and how to ensure they have been processed successfully before posting the next batch. How the provider can authenticate their requests through the Provider API by retrieving a Sage ID bearer token has also been covered.

What’s next?

Next, take a look at the offboarding flow. This covers how to disconnect an account.

Was this helpful?