Software Engineering @ Spotify. Previously Senior Software Engineer @ Goldman Sachs, Quant @ Natixis.

August 14, 2019

Building a Monzo Bank API application


I have three bank accounts across several banking providers. Everytime I need to find the total balance, I have to login to three different apps, check my balance in each of them and sum them up.

I needed an app which automates this work for me.

I started researching ways of doing this. I came across the Open Banking initiative. It allows individuals and businesses to access financial information with the approval of their customers. There exists a number of apps which offer this functionality. Most of them are paid.


I decided to build a bank balance aggregator myself, using the Open Banking APIs across my bank providers. I took a look at the developers documentation for the three banks where I have accounts, Monzo is one of them. They have a very clear documentation, with step-by-step instructions on how to implement the OAuth2.0 flow.

I implemented a web app, using React for a basic front-end, Express in the back-end, managed by webpack.


We need to do a number of things before implementing OAuth:

Credentials to access the API:

  1. Go to Monzo’s developers portal. You can sign-in using the email address linked to your Monzo account.
  2. Add an OAuth client in the Client tab, this will create a profile for your app, where you define your redirect URI.
  3. Keep client_secret and client_id generated in step 2, we will need these to get access_token from the Monzo OAuth2.0 server.

Setup the foundation for the application:

Implement a minimal app which supports React, Babel, Node.js, Express, and is managed by webpack. The source code for a minimal configuration can be found here.


We need two configuration files to store the information about the client:

  • oauth_credentials: a file for client parameters: client_id, client_secret and redirect_uri.
  • oauth_urls: a file for the oauth endpoints - this is useful for code clarity.

To get the balance for an account, we need to follow these steps:

  1. Get an authorisation code from Monzo’s OAuth server - this will redirect the client to Monzo’s portal.

    app.get("/monzopage", (req, res) => {
        urls.base_url +
          "?client_id=" +
          params.client_id +
          "&redirect_uri=" +
          params.redirect_uri +
          "&response_type=" +
          params.response_type +
          "&state=" +
  2. Exchange the authorisation code for an access token, store the latter and redirect to the home page (at this step I store the token in a global variable, this can be improved).

    app.get("/oauth/callback", (req, res) => {
      global.code = req.query.code;
      var client_id = params.client_id;
      var client_secret = params.client_secret;
      var redirect_uri = params.redirect_uri;
      var grant_type = params.grant_type;
      var url = urls.token_url;
          url: url,
          form: {
        (err, response, body) => {
          var jsonBody = JSON.parse(body);
          global.access_token = jsonBody.access_token;
  3. Get the balance using the access token.We start by getting the account ID:

    app.get("/account", function(req, res) {
      var account_type = params.account_type;
      var access_token = global.access_token;
      var account_url = urls.account_url;
          url: account_url + "?account_type=" + account_type,
          headers: {
            Authorization: "Bearer " + access_token
        (error, response, body) => {
          var jsonBody = JSON.parse(body);
          var account_id = jsonBody.accounts[0].id;
            account_id: account_id

    Then we get the balance for the given account ID:

    app.get("/balance", (req, res) => {
      var account_id = req.query.account_id;
      var balance_url = urls.balance_url;
          url: balance_url + "?account_id=" + account_id,
          headers: {
            Authorization: "Bearer " + global.access_token
        (error, response, body) => {
          var balances = JSON.parse(body);
            balances: balances

The minimal React app makes these calls:

import React from "react";
import fetch from "isomorphic-fetch";

class App extends React.Component {
  state = {
    account_id: "",
    balance: ""

  loginToMonzo() {

  getBalance() {
      .then(result => result.json())
      .then(response => {
        this.setState({ account_id: response.account_id });
        fetch("/balance?account_id=" + this.state.account_id)
          .then(result => result.json())
          .then(response => {
            this.setState({ balance: response.balances.balance });

  render() {
    return (
        <button onClick={e => this.loginToMonzo(e)}>Login to Monzo</button>
        <button onClick={e => this.getBalance(e)}>Get balance</button>

export default App;

Next steps

Hope this helped you understand how to interact with Monzo’s API to obtain the balance. We can improve it by:

  • Implementing the access token refresh mechanism.
  • changing the access token storage to be more secure - in a database for instance.
  • Implementing a minimalist design for the page - currently sketching :).

If you get stuck with any step or need help, you can reach out to me via Twitter.

©2020 Salwa Fathallah

Hugo, Kiss & bb