Up Bank Integration (Australian Neobank) - Node-Red w/ Home Assistant

Tags: #<Tag:0x00007f7396edf7e0>

Here in Australia one of our neobanks, Up, recently released an API. It seemed like a fun weekend project to get it integrated into my Home Assistant/Node Red setup. I’m still learning the ropes with all these systems, so wanted to share what I’d done to help other Up users and get some feedback on my setup. I hope I’ve managed to make the core functionality really easy to deploy for anyone using HA/NR.

The first step is to register for the Up API and obtain your bearer token. Their guide gives steps on doing this with curl, I used Postman, you can do this however you like. If you want to use webhooks, you’ll need to register your webhook endpoint via the Up API, also following the steps in their guide. My flow uses “/api/up” for the endpoint but you can use whatever you want. The webhook is optional though, you can rely exclusively on the inject node for periodic updates if you prefer.

Then you’ll need to deploy the following NR flow, and put your bearer into the Set Bearer and Inject Bearer nodes.

[
   {
      "id":"d7911825.3f6ad8",
      "type":"http in",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Webhook",
      "url":"/api/up",
      "method":"post",
      "upload":true,
      "swaggerDoc":"",
      "x":110,
      "y":80,
      "wires":[
         [
            "53dfbba1.6f7794",
            "43a8fb96.292274",
            "9fbed058.18f4c"
         ]
      ]
   },
   {
      "id":"53dfbba1.6f7794",
      "type":"http response",
      "z":"1a80a0df.9dc3ff",
      "name":"HTTP  Res",
      "statusCode":"",
      "headers":{

      },
      "x":330,
      "y":80,
      "wires":[

      ]
   },
   {
      "id":"43a8fb96.292274",
      "type":"debug",
      "z":"1a80a0df.9dc3ff",
      "name":"Webhook Debug",
      "active":true,
      "tosidebar":true,
      "console":false,
      "tostatus":false,
      "complete":"true",
      "targetType":"full",
      "x":350,
      "y":40,
      "wires":[

      ]
   },
   {
      "id":"9fbed058.18f4c",
      "type":"change",
      "z":"1a80a0df.9dc3ff",
      "name":"Set Bearer",
      "rules":[
         {
            "t":"set",
            "p":"payload.bearer",
            "pt":"msg",
            "to":"up:yeah:YOURBEARERHERE",
            "tot":"str"
         }
      ],
      "action":"",
      "property":"",
      "from":"",
      "to":"",
      "reg":false,
      "x":110,
      "y":120,
      "wires":[
         [
            "bc8e510a.051df"
         ]
      ]
   },
   {
      "id":"db8688c.78b8878",
      "type":"inject",
      "z":"1a80a0df.9dc3ff",
      "name":"Inject Bearer",
      "topic":"",
      "payload":"{\"bearer\":\"up:yeah:YOURBEARERHERE\"}",
      "payloadType":"json",
      "repeat":"60",
      "crontab":"",
      "once":true,
      "onceDelay":0.1,
      "x":120,
      "y":200,
      "wires":[
         [
            "bc8e510a.051df"
         ]
      ]
   },
   {
      "id":"bc8e510a.051df",
      "type":"function",
      "z":"1a80a0df.9dc3ff",
      "name":"Create Request",
      "func":"msg.headers = {\n    \"Authorization\": \"Bearer \" + msg.payload.bearer\n}\n\nreturn msg;\n\n",
      "outputs":1,
      "noerr":0,
      "x":120,
      "y":160,
      "wires":[
         [
            "dcac08db.5827c8",
            "6df2aa1c.339524"
         ]
      ]
   },
   {
      "id":"dcac08db.5827c8",
      "type":"http request",
      "z":"1a80a0df.9dc3ff",
      "name":"Requesting  Balances",
      "method":"GET",
      "ret":"obj",
      "paytoqs":false,
      "url":"https://api.up.com.au/api/v1/accounts",
      "tls":"",
      "proxy":"",
      "authType":"",
      "x":360,
      "y":120,
      "wires":[
         [
            "b9239811.41a128",
            "e581b9dc.690de8"
         ]
      ]
   },
   {
      "id":"6df2aa1c.339524",
      "type":"http request",
      "z":"1a80a0df.9dc3ff",
      "name":"Request Transactions",
      "method":"GET",
      "ret":"obj",
      "paytoqs":false,
      "url":"https://api.up.com.au/api/v1/transactions",
      "tls":"",
      "proxy":"",
      "authType":"",
      "x":360,
      "y":160,
      "wires":[
         [
            "b9239811.41a128",
            "e581b9dc.690de8"
         ]
      ]
   },
   {
      "id":"b9239811.41a128",
      "type":"join",
      "z":"1a80a0df.9dc3ff",
      "name":"",
      "mode":"custom",
      "build":"array",
      "property":"payload",
      "propertyType":"msg",
      "key":"topic",
      "joiner":"\\n",
      "joinerType":"str",
      "accumulate":false,
      "timeout":"",
      "count":"2",
      "reduceRight":false,
      "reduceExp":"",
      "reduceInit":"",
      "reduceInitType":"",
      "reduceFixup":"",
      "x":590,
      "y":160,
      "wires":[
         [
            "163d9ac.639fe65"
         ]
      ]
   },
   {
      "id":"163d9ac.639fe65",
      "type":"function",
      "z":"1a80a0df.9dc3ff",
      "name":"Create Account Name Array",
      "func":"msg.acctNameIndex = {\n    \"acct1\": {\n        \"id\": msg.payload[0].data[0].id,\n        \"name\": msg.payload[0].data[0].attributes.displayName\n    },\n    \"acct2\": {\n        \"id\": msg.payload[0].data[1].id,\n        \"name\": msg.payload[0].data[1].attributes.displayName\n    },\n}\n\n\nreturn msg;\n ",
      "outputs":1,
      "noerr":0,
      "x":380,
      "y":200,
      "wires":[
         [
            "577763df.17851c"
         ]
      ]
   },
   {
      "id":"577763df.17851c",
      "type":"function",
      "z":"1a80a0df.9dc3ff",
      "name":"Append Acct Names to Transactions Loop",
      "func":"for (i = 0; i < 19; i++) {\n\nif (msg.payload[1].data[i].relationships.account.data.id == msg.acctNameIndex.acct1.id) {\n  msg.payload[1].data[i].acctName = msg.acctNameIndex.acct1.name;\n} else if (msg.payload[1].data[i].relationships.account.data.id == msg.acctNameIndex.acct2.id) {\n  msg.payload[1].data[i].acctName = msg.acctNameIndex.acct2.name;\n} else {\n  msg.payload[1].data[i].acctName = \"Error\";\n}\n\n}\n\nreturn msg;",
      "outputs":1,
      "noerr":0,
      "x":480,
      "y":240,
      "wires":[
         [
            "cde892e9.a3f6d",
            "dc80980b.90e738",
            "f5cb89bb.4fa188",
            "18507de1.38bf82",
            "95d1ec6d.a99c5",
            "70580ffc.43591",
            "adfb6c91.38004"
         ]
      ]
   },
   {
      "id":"e581b9dc.690de8",
      "type":"http response",
      "z":"1a80a0df.9dc3ff",
      "name":"",
      "statusCode":"",
      "headers":{

      },
      "x":590,
      "y":120,
      "wires":[

      ]
   },
   {
      "id":"cde892e9.a3f6d",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Balance 1",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Balance 1"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":"AUD"
         }
      ],
      "state":"payload[0].data[0].attributes.balance.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"displayName",
            "value":"payload[0].data[0].attributes.displayName",
            "valueType":"msg"
         },
         {
            "property":"accountType",
            "value":"payload[0].data[0].attributes.accountType",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[0].data[0].attributes.balance.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"balance",
            "value":"payload[0].data[0].attributes.balance.value",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":840,
      "y":40,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"f5cb89bb.4fa188",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Transaction 1",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Transaction 1"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":""
         }
      ],
      "state":"payload[1].data[0].attributes.amount.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"status",
            "value":"payload[1].data[0].attributes.status",
            "valueType":"msg"
         },
         {
            "property":"amount",
            "value":"payload[1].data[0].attributes.amount.value",
            "valueType":"msg"
         },
         {
            "property":"description",
            "value":"payload[1].data[0].attributes.description",
            "valueType":"msg"
         },
         {
            "property":"message",
            "value":"payload[1].data[0].attributes.message",
            "valueType":"msg"
         },
         {
            "property":"foreignAmount",
            "value":"payload[1].data[0].attributes.foreignAmount",
            "valueType":"msg"
         },
         {
            "property":"settledAt",
            "value":"payload[1].data[0].attributes.settledAt",
            "valueType":"msg"
         },
         {
            "property":"createdAt",
            "value":"payload[1].data[0].attributes.createdAt",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[1].data[0].attributes.amount.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"acctName",
            "value":"payload[1].data[0].acctName",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":850,
      "y":120,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"dc80980b.90e738",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Balance 2",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Balance 2"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":"AUD"
         }
      ],
      "state":"payload[0].data[1].attributes.balance.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"displayName",
            "value":"payload[0].data[1].attributes.displayName",
            "valueType":"msg"
         },
         {
            "property":"accountType",
            "value":"payload[0].data[1].type",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[0].data[1].attributes.balance.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"balance",
            "value":"payload[0].data[1].attributes.balance.value",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":840,
      "y":80,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"9fa1be87.aed34",
      "type":"debug",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Debug",
      "active":true,
      "tosidebar":true,
      "console":false,
      "tostatus":false,
      "complete":"true",
      "targetType":"full",
      "x":1120,
      "y":160,
      "wires":[

      ]
   },
   {
      "id":"18507de1.38bf82",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Transaction 2",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Transaction 2"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":""
         }
      ],
      "state":"payload[1].data[1].attributes.amount.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"status",
            "value":"payload[1].data[1].attributes.status",
            "valueType":"msg"
         },
         {
            "property":"amount",
            "value":"payload[1].data[1].attributes.amount.value",
            "valueType":"msg"
         },
         {
            "property":"description",
            "value":"payload[1].data[1].attributes.description",
            "valueType":"msg"
         },
         {
            "property":"message",
            "value":"payload[1].data[1].attributes.message",
            "valueType":"msg"
         },
         {
            "property":"foreignAmount",
            "value":"payload[1].data[1].attributes.foreignAmount",
            "valueType":"msg"
         },
         {
            "property":"settledAt",
            "value":"payload[1].data[1].attributes.settledAt",
            "valueType":"msg"
         },
         {
            "property":"createdAt",
            "value":"payload[1].data[1].attributes.createdAt",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[1].data[1].attributes.amount.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"acctName",
            "value":"payload[1].data[1].acctName",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":850,
      "y":160,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"95d1ec6d.a99c5",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Transaction 3",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Transaction 3"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":""
         }
      ],
      "state":"payload[1].data[2].attributes.amount.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"status",
            "value":"payload[1].data[2].attributes.status",
            "valueType":"msg"
         },
         {
            "property":"amount",
            "value":"payload[1].data[2].attributes.amount.value",
            "valueType":"msg"
         },
         {
            "property":"description",
            "value":"payload[1].data[2].attributes.description",
            "valueType":"msg"
         },
         {
            "property":"message",
            "value":"payload[1].data[2].attributes.message",
            "valueType":"msg"
         },
         {
            "property":"foreignAmount",
            "value":"payload[1].data[2].attributes.foreignAmount",
            "valueType":"msg"
         },
         {
            "property":"settledAt",
            "value":"payload[1].data[2].attributes.settledAt",
            "valueType":"msg"
         },
         {
            "property":"createdAt",
            "value":"payload[1].data[2].attributes.createdAt",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[1].data[2].attributes.amount.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"acctName",
            "value":"payload[1].data[2].acctName",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":850,
      "y":200,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"70580ffc.43591",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Transaction 4",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Transaction 4"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":""
         }
      ],
      "state":"payload[1].data[3].attributes.amount.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"status",
            "value":"payload[1].data[3].attributes.status",
            "valueType":"msg"
         },
         {
            "property":"amount",
            "value":"payload[1].data[3].attributes.amount.value",
            "valueType":"msg"
         },
         {
            "property":"description",
            "value":"payload[1].data[3].attributes.description",
            "valueType":"msg"
         },
         {
            "property":"message",
            "value":"payload[1].data[3].attributes.message",
            "valueType":"msg"
         },
         {
            "property":"foreignAmount",
            "value":"payload[1].data[3].attributes.foreignAmount",
            "valueType":"msg"
         },
         {
            "property":"settledAt",
            "value":"payload[1].data[3].attributes.settledAt",
            "valueType":"msg"
         },
         {
            "property":"createdAt",
            "value":"payload[1].data[3].attributes.createdAt",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[1].data[3].attributes.amount.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"acctName",
            "value":"payload[1].data[3].acctName",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":850,
      "y":240,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"adfb6c91.38004",
      "type":"ha-entity",
      "z":"1a80a0df.9dc3ff",
      "name":"Up Transaction 5",
      "server":"788025f4.1f0d8c",
      "version":1,
      "debugenabled":false,
      "outputs":1,
      "entityType":"sensor",
      "config":[
         {
            "property":"name",
            "value":"Up Transaction 5"
         },
         {
            "property":"device_class",
            "value":""
         },
         {
            "property":"icon",
            "value":"mdi:piggy-bank"
         },
         {
            "property":"unit_of_measurement",
            "value":""
         }
      ],
      "state":"payload[1].data[4].attributes.amount.value",
      "stateType":"msg",
      "attributes":[
         {
            "property":"status",
            "value":"payload[1].data[4].attributes.status",
            "valueType":"msg"
         },
         {
            "property":"amount",
            "value":"payload[1].data[4].attributes.amount.value",
            "valueType":"msg"
         },
         {
            "property":"description",
            "value":"payload[1].data[4].attributes.description",
            "valueType":"msg"
         },
         {
            "property":"message",
            "value":"payload[1].data[4].attributes.message",
            "valueType":"msg"
         },
         {
            "property":"foreignAmount",
            "value":"payload[1].data[4].attributes.foreignAmount",
            "valueType":"msg"
         },
         {
            "property":"settledAt",
            "value":"payload[1].data[4].attributes.settledAt",
            "valueType":"msg"
         },
         {
            "property":"createdAt",
            "value":"payload[1].data[4].attributes.createdAt",
            "valueType":"msg"
         },
         {
            "property":"currencyCode",
            "value":"payload[1].data[4].attributes.amount.currencyCode",
            "valueType":"msg"
         },
         {
            "property":"acctName",
            "value":"payload[1].data[4].acctName",
            "valueType":"msg"
         }
      ],
      "resend":true,
      "outputLocation":"",
      "outputLocationType":"none",
      "inputOverride":"allow",
      "x":850,
      "y":280,
      "wires":[
         [
            "9fa1be87.aed34"
         ]
      ]
   },
   {
      "id":"788025f4.1f0d8c",
      "type":"server",
      "z":"",
      "name":"Home Assistant",
      "legacy":false,
      "addon":false,
      "rejectUnauthorizedCerts":true,
      "ha_boolean":"y|yes|true|on|home|open",
      "connectionDelay":true,
      "cacheJson":true
   }
]

Once deployed, if Home Assistant is properly connected to Node Red, you should see some sensors in HA with details in the attributes:

Once these appear, create a group in groups.yaml:

up_transactions:
  name: Up Transactions
  entities:
    - sensor.up_transaction_1
    - sensor.up_transaction_2
    - sensor.up_transaction_3
    - sensor.up_transaction_4
    - sensor.up_transaction_5

Once grouped, create a Lovelace card by copying this yaml into a Manual card:

cards:
  - content: '## Up Bank'
    type: markdown
  - cards:
      - detail: 2
        entity: sensor.up_balance_1
        graph: line
        hours_to_show: 72
        icon: 'mdi:cash'
        name: Spending
        type: sensor
      - entity: sensor.up_balance_2
        graph: line
        hours_to_show: 72
        name: Rounding
        type: sensor
    type: horizontal-stack
  - content: >
      #### Recent Transactions:

      {% for transaction in states.group.up_transactions.attributes.entity_id
      -%}


      {# Check if more than one day old, and apply formatting #}

      *{%- if ((as_timestamp(now()) -
      as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60 / 24) |
      round(0) > 0 -%}
        {{ ((as_timestamp(now()) - as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60 / 24) | round(0) }} day
          {#- Pluralise if not 1 -#}{% if ((as_timestamp(now()) - as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60) | round(0) != 1  %}s{%- endif -%}

      {# Check if more than one hour old, and apply formatting #}

      {%- elif ((as_timestamp(now()) -
      as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60) | round(0) >
      0 -%}
        {{ ((as_timestamp(now()) - as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60) | round(0) }} hr
          {#- Pluralise if not 1 -#}{%- if ((as_timestamp(now()) - as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60) | round(0) != 1  -%}s{%- endif -%}

      {# Otherwise, format age for minutes #}

      {%- else -%} {{ ((as_timestamp(now()) -
      as_timestamp(state_attr(transaction,"settledat"))) / 60) | round(0) }} min
        {#- Pluralise if not 1 -#}{%- if ((as_timestamp(now()) - as_timestamp(state_attr(transaction,"settledat"))) / 60 / 60) | round(0) != 1  -%}s{%- endif -%}
      {%- endif %} ago*


      {{- " " -}}



      {# Print amount value with bold formatting #}

      **${{- state_attr(transaction,'amount') | float | abs -}}**

      {{- " " -}}


      {# Change language for positive/negative #}

      {%- if state_attr(transaction, 'amount') | int  > 0 -%}
         came into
      {%- elif state_attr(transaction, 'amount') | int  < 0 -%}
         went out of
      {%- endif -%}

      {{- " " -}}


      {# Change language for positive/negative #}

      {{- state_attr(transaction,"acctname") }}

      {{ state_attr(transaction,'description') }} {{
      state_attr(transaction,'message') }}


      {% endfor %}
    type: markdown
type: vertical-stack

The result should look like this:

The webhook is very convenient for any kind of notifications you might want to integrate. This next example is a lot more dependent on my particular light/speaker configuration and won’t be as easy to drop into an existing config, but should show how simple it is to connect webhooks to a notification system.

Had to remove the code to fit within the character limit, but if anyone is interested I’ll put this flow in a Pastebin or something.

1 Like