Accessing Transactional Data

Learn how to access a connected user's transactional data

ℹ️

This guide is intended for developers using Akahu's enduring account connectivity. Information provided may not be relevant for those using one-off account connectivity.

Using Akahu's API it is possible to fetch transaction data from a user's connected financial accounts. A transaction represents a single line item in that account's ledger, just like you'd expect to see on a bank statement or in your internet banking.

Please note: Akahu serves pending transactions and settled (or posted) transactions via separate API endpoints. Pending transactions are those which have been lodged with the financial institution but are still being processed (and are liable to change). Depending on the institution, transactions may remain in a pending state for several days, so if your users expect to see their most recent transactions in your app it is important to query transactions from both of these endpoints.

Prerequisites

Before you can follow this guide, you will need:

  • To be able to make requests to the Akahu API (see here for instructions).
  • A user access token (<<apiKey>>). Follow the Getting Started Guide to obtain one.
  • Your app access token (<<appToken>>). You should get this when you create your app.
  • An Akahu account with at least one account connected. This account must have transactions, preferably a few so that you can practice filtering them in different ways.

To determine if your account has transactions, make a GET request to the /accounts endpoint.
Locate your account in the results and look for the attributes key. If your account attributes include TRANSACTIONS, then the account has transactions.

Making the Request

API Reference

Using your language of choice, make a GET request to the https://api.akahu.io/v1/transactions endpoint, with the following headers:

Authorization: Bearer {{user access token}}
X-Akahu-ID: {{app access token}}

Replace the {{user access token}} with your user access token, and {{app access token}} with your app access token.

Handling the response

As in Accessing Account Data, you should handle any HTTP error codes returned by the API.

The API response will look like:

{
  "success": true,
  "items": [
    {
      "_id": "trans_1111111111111111111111111",
      "_account": "acc_1111111111111111111111111",
      "_connection": "conn_1111111111111111111111111",
      "created_at": "2020-01-01T01:00:00.000Z",
      "updated_at": "2020-01-01T01:00:00.000Z",
      "date": "2020-01-01T00:00:00.000Z",
      "description": "{RAW TRANSACTION DESCRIPTION}",
      "amount": -5.5,
      "balance": 100,
      "type": "EFTPOS"
    }
    // ...
  ],
  "cursor": {
    "next": "abc123...321cba"
  }
}

Breaking down this response:

At the top level, the key success is true. That means that the request was successful.

The items key contains a list of Akahu Transactions. Different types of accounts have different levels of detail in their transactions, depending on what is available.

The cursor key allows you to paginate through the results. This allows you to efficiently get transactions for large time-spans, without having to handle gigabyte response sizes. See the section on Pagination below for more information on working with cursors.

Getting a Date Range

📘

Timezones

Akahu's API returns all dates and times in UTC. If no timezone is specified on timestamps in the request, Akahu will assume that the times are also UTC. See here to learn how to specify a timezone in a ISO 8601 date-time string.

By default, the API will return all transactions accessible to your app. If you want to retrieve data for a specific period, you can specify the start and end query parameters. These should be ISO 8601 formatted date strings, for example "2020-01-10" to specify the 10th of January 2020. If you require additional precision, a full ISO 8601 date-time string can be supplied.

Akahu applies a restriction on how far back you can view transactions. This restriction is calculated based on two factors:

  • The date the user gave the app consent to access transaction data.
  • Your app setting for historical transactions.

The date the user gave consent (either when the user completes the OAuth flow, or when you create your personal app), can be found as access_granted_at on the /me endpoint.

Your app setting is set based on its need for historical transactions - for example an app that helps users with tax calculations would likely need 365 days or more of historical transactions, while an app that sends you a weekly email of your spending would likely only need 7 days. If you are using a personal app, it will be given access to 365 days of transactions. If you are creating a production app, we will help you arrive at an appropriate date setting for your app.

To calculate the earliest date that your app can fetch transactions, simply subtract the app date setting from the date the user gave the app consent. For example, if your app was set up with access to 365 days of historical transactions, and the user gave the app consent on the 15th of January 2010, your app would be able to request transactions dated from the 15th of January 2009 onwards.

ℹ️

Limitations of financial institutions

Some financial institutions limit the data range of historical data that is available. Known limits are documented on our Supported Integrations page.

Getting Transactions For a Single Account

By default, the API will return transactions from all accounts you have access to. To retrieve transactions from a single account, update the uri to https://api.akahu.io/v1/accounts/{_id}/transactions, where {_id} is replaced by the Akahu Account ID you wish to retrieve transactions for.

Enriched Data

If your app has permission to view enriched transaction data, you will see three additional fields on many debit (outbound) transactions:

  • merchant The merchant associated with the transaction, for example Four Square.
  • category The category that the merchant has been assigned to.
  • meta Other metadata that has been extracted from the raw transaction data.

More detail about these enriched fields can be found in our Transaction Model Documentation

Pagination

For larger queries (those that have many transactions or span long time-periods), you will probably not receive all transactions for your query at once. Instead, you may only receive the first "page" of results. If a response does not contain all transactions for the provided query, it will also include a "cursor" that points to the next page of results.

To access subsequent pages, simply take the cursor.next value from each response and make a new request, supplying this value using the cursor query parameter. In response, you will receive the next page of results, along with a new cursor.next value.

Once you have reached the final page of results, the value of cursor.next will be null. This means that all transactions that match your query have been returned. Passing this null cursor back to the API will result in an error response.

See below for an example taken from our Javascript SDK:

const query = {
  // start: "2021-01-01T00:00:00.000Z",
  // end: "2021-01-02T00:00:00.000Z",
};

const transactions = [];

do {
  // Transactions are returned one page at a time
  const page = await akahu.transactions.list(userToken, query);
  // Store the returned transaction `items` from each page
  transactions.push(...page.items);
  // Update the cursor to point to the next page
  query.cursor = page.cursor.next;
  // Continue until the server returns a null cursor
} while (query.cursor !== null);

Keeping Transactions Synchronised

Most banks do not provide a stable unique identifier for each transaction. This means that Akahu must rely on transaction attributes (such as date, description, and amount) to uniquely identify each transaction in a user's account. This is important because when Akahu refreshes a user's transaction data from the bank, we need to know which records are new (and need to be inserted), which have been modified (and need to be updated), which records are unchanged, and which have been deleted.

Unfortunately, banks often mutate a transaction in the days (or weeks) following its posting. The date, description, and balance of a transaction may change during this period. This can make it challenging to identify which transactions are new, and which have simply been mutated. Akahu employs a range of heuristics and matching algorithms to ensure that these cases are captured and handled correctly. This system correctly identifies the vast majority (>99.9%) of transactions, allowing us to provide API consumers with a unique identifier for each transaction that will remain stable between queries. When a transaction is modified by the bank, we update our copy in-place to reflect those changes. When a transaction is removed by the bank, Akahu's copy is also removed. You can subscribe to TRANSACTION webhook events to be notified of such changes.

The ~0.1% of cases where we are unable to confidently identify a transaction are usually caused by the bank mutating a transaction beyond recognition. When faced with this situation, Akahu reverts to a diff-based synchronisation approach. This means that our copy of the transaction will be deleted and replaced with the new version which will have a new identifier. While this happens relatively infrequently, it is important that your app correctly handles deletion of transactions to avoid duplicate entries in your local copy of the data.

TL;DR

  • Akahu provides API consumers with a stable, unique identifier for each transaction.
  • A small percentage of transactions will receive a new identifier if heavily modified by the bank.
  • Your code should expect to handle addition, modification, and deletion of transactions when fetching them from Akahu.
  • You can use webhooks to respond to these updates as they happen.

Pending Transactions

Pending transactions are transactions that are still being processed by the bank. These transactions are made available at a separate endpoint and contain less information than transactions that have been settled. For example, pending transactions are not assigned a unique identifier and are not enriched by Akahu. This is because New Zealand banks typically do not serve a consistent view of pending transactions. Pending transactions are liable to change significantly as they are processed, so it would be misleading to assign them a unique identifier. When working with pending transactions it is recommended that you completely rebuild your local copy of this data (i.e. delete then re-create) each time you query them from Akahu.

Conclusion

You should now be able to:

  • Obtain recent user transactions
  • Filter transactions by date
  • Get transactions for a given account