Skip to main content

Access ubank's API.

Project description

ubank

Access ubank's API.

Contents

Getting started

Install ubank with pip (Python 3.8+ is required):

$ pip install ubank

Before accessing the API, you'll first need to enrol a new device with ubank. Running ubank as a module helps with this task:

$ python -m ubank --help
usage: ubank.py [-h] [-o FILE] [-v] username

Enrols new device with ubank. You will be asked for your ubank password and secret code interactively.

positional arguments:
  username              ubank username

optional arguments:
  -h, --help            show this help message and exit
  -o FILE, --output FILE
                        write JSON device credentials to file (default: write to stdout)
  -v, --verbose         displays httpx INFO logs

We'll enrol a new device and save the credentials to device.json. Keep this file safe! You'll be prompted for your ubank password and security code during this step.

$  python -m ubank name@domain.com --output device.json
Enter ubank password:
Enter security code sent to 04xxxxx789: 123456
$ cat device.json
{
  "hardware_id": "35bd47b0-eced-4fb4-88e1-24657c2500ec",
  "device_id": "cc1d3291-8e7d-45fc-845b-326b65bffcb1",
  "device_meta": "{\"appVersion\": \"15.11.1\", \"binaryVersion\": \"15.11.1\", \"deviceName\": \"iPhone19-1\", \"environment\": \"production\", \"instance\": \"live\", \"native\": true, \"platform\": \"ios\"}",
  "hashed_pin": "N0ZsiU81f+qiOZvs424E06AasHBlHsSlH9Fj1J0Sz5c=",
  "secret": "c3e59465-2449-4692-8d0a-6dc9bb8b2ae2",
  "auth_key": "pLzKjKs0FW104tqaj5qD3wYmZf0Q+udRCsRgST1gRGwh9iaxVf5qZdn+LtidvqSx20Y=",
  "email": "name@domain.com",
  "mobile_number": "+61423456789",
  "user_id": "51457aec-9fb4-45c4-9ed0-4d17b70665ec",
  "username": "48b16c6f-19a5-46e7-855e-5d6922882276",
  "token": "dw2FYNdTRLgIS8YxZlQ0RnihkpgxRB/+a/o3vmQWWiRtrF11H4ZjA8ywZfaoUYK/Gkc="
}

Accessing ubank's API

You won't use your username and password to access ubank's API. Instead, you'll use the enrolled device's credentials (stored in device.json).

Instantiate a ubank.Device from device.json:

import json
import ubank

with open("device.json") as file:
    device = ubank.Device(**json.load(file))

Next, we'll instantiate ubank.Client with the device created above. Use this class as a context manager. This ensures ubank sessions and HTTP connections are properly cleaned when leaving the with block.

ubank.Client's base_url is set to https://api.ubank.com.au/, so only the API path is required when making requests.

[!IMPORTANT] You must store the instance's .device attribute after instantiation. Otherwise the stored device credentials will be expired and you'll need to re-enrol.

Instantiating ubank.Client refreshes the auth_key and long life token, held in the .device attribute.

with ubank.Client(device) as client:
    with open("device.json", "w") as file:
        file.write(client.device.dumps())
    print(client.get("/app/v1/accounts/summary").json())

{'linkedBanks': [{'bankId': 1, 'shortBankName': 'ubank', 'accounts': [{'label': 'Spend', 'type': 'TRANSACTION', 'balance': {'currency': 'AUD', 'current': 100, 'available': 100}, 'status': 'Active', 'id': '695db516-b0e2-4807-baca-77314a6257ce', 'nickname': 'Spend', 'number': '12345678', 'bsb': '670864', 'lastBalanceRefresh': '2024-01-02T00:00:00.000Z', 'openDate': '2024-01-01T00:00:00.000Z', 'isJointAccount': False}, {'label': 'Save', 'type': 'SAVINGS', 'balance': {'currency': 'AUD', 'current': 1200.44, 'available': 1200.44}, 'status': 'Active', 'id': '5bad6edf-247e-4221-9bfc-e7608f5984cb', 'nickname': 'Save', 'number': '23456789', 'bsb': '670864', 'lastBalanceRefresh': '2024-01-02T00:00:00.000Z', 'openDate': '2024-01-01T00:00:00.000Z', 'isJointAccount': False}]}]}

API endpoints

Here are some API endpoints to try:

with ubank.Client(device) as client:
    with open("device.json", "w") as file:
        file.write(client.device.dumps())
    print(client.get("/app/v1/accounts").json())
    print(client.get("/app/v1/accounts/summary").json())
    print(client.get("/app/v1/achievements").json())
    print(client.get("/app/v1/campaigns").json())
    print(client.get("/app/v1/cards").json())
    print(client.get("/app/v1/contacts").json())
    print(client.get("/app/v1/customer-details").json())
    print(client.get("/app/v1/insights").json())
    print(client.get("/app/v1/insights/interest").json())
    print(client.get("/app/v1/products").json())
    print(client.get("/app/v1/promotions").json())
    print(client.get("/app/v1/savings-goals").json())
    print(client.get("/app/v1/tfn").json())

Testing

Pull credentials from AWS:

aws-vault exec brodie@oasis -- python
Opening the SSO authorization page in your default browser (use Ctrl-C to abort)
https://device.sso.ap-southeast-2.amazonaws.com/?user_code=YMMV-CUMT
>>> import json
>>>
>>> import boto3
>>>
>>> import ubank
>>>
>>>
>>> def get_device(parameter_name="/portfolio/ubank-device"):
...     """Returns ubank enrolled device from AWS Parameter Store."""
...     return ubank.Device(
...         **json.loads(
...             # Retrieve JSON string from decrypted parameter value.
...             boto3.client("ssm", region_name="us-east-1").get_parameter(
...                 Name=parameter_name, WithDecryption=True
...             )["Parameter"]["Value"]
...         )
...     )
...
>>>
>>> def save_device(device, parameter_name="/portfolio/ubank-device"):
...     """Saves ubank device credentials to AWS Parameter Store."""
...     return boto3.client("ssm", region_name="us-east-1").put_parameter(
...         Name=parameter_name,
...         Value=device.dumps(),
...         Type="SecureString",
...         Overwrite=True,
...     )
...
>>>
>>> # Get ubank account balances and trusted cookie.
>>> device = get_device()
>>> with ubank.Client(device) as client:
...     # Update stored device credentials.
...     save_device(client.device)
...     for account in client.get("/app/v1/accounts/summary").json()["linkedBanks"][0][
...         "accounts"
...     ]:
...         print(account)
...
{'Version': 77, 'Tier': 'Standard', 'ResponseMetadata': {'RequestId': '1dd6cfff-dead-beef-asdf-123ead7e3ba0', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Thu, 1 Nov 1970 01:23:45 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '32', 'connection': 'keep-alive', 'x-amzn-requestid': '1dd6cfff-dead-beef-asdf-123ead7e3ba0'}, 'RetryAttempts': 0}}
{'label': 'Spend account', 'type': 'TRANSACTION', 'balance': {'currency': 'AUD', 'current': 1000.00, 'available': 1000.00}, 'status': 'Active', 'id': '9a293f00-c000-45b2-b21e-28cf09453f73', 'nickname': 'USpend', 'number': '19057097', 'bsb': '670864', 'lastBalanceRefresh': '1970-01-01T01:23:45.678Z', 'openDate': '1970-01-01T01:23:45.678Z', 'isJointAccount': False, 'depositProductData': {'interestTiers': [{'interestRate': 0, 'minimumRange': 0}]}}
{'label': 'Save account', 'type': 'SAVINGS', 'balance': {'currency': 'AUD', 'current': 1000000.00, 'available': 1000000.00}, 'status': 'Active', 'id': '88bcd861-21ad-48d9-8c3d-d789c5845252', 'nickname': 'USave', 'number': '00000000', 'bsb': '000000', 'lastBalanceRefresh': '1970-01-01T01:23:45.678Z', 'openDate': '1970-01-01T01:23:45.678Z', 'isJointAccount': False, 'depositProductData': {'interestTiers': [{'interestRate': 5.5, 'minimumRange': 0, 'maximumRange': 100000}, {'interestRate': 5, 'minimumRange': 100000.01, 'maximumRange': 250000}, {'interestRate': 0, 'minimumRange': 250000.01}], 'interestPaymentFrequency': {'interestPaymentCountPerPeriod': 1, 'interestPeriod': '1 Month', 'interestPaymentSchedule': 'End'}}}
>>>

Release

Bump project version. e.g.,

$ poetry version patch
Bumping version from 0.1.1 to 0.1.2

Publish to PyPI:

$ read -s PASSWORD
$ poetry publish --build -u __token__ -p "$PASSWORD"

Release workflow

micromamba create --file environment.yml --yes
micromamba activate "${PWD##*/}" # If dir name == environment name...
poetry install
$ read -s PASSWORD
$ poetry publish --build -u __token__ -p "$PASSWORD"

Changelog

1.1.0

1.0.0

  • Drop Playwright requirement.
  • Re-implement with simpler and lightweight httpx libary.
  • Easier access to full ubank API.

0.1.2

  • Automate ubank access using Playwright headless browser.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ubank-1.1.0.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ubank-1.1.0-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file ubank-1.1.0.tar.gz.

File metadata

  • Download URL: ubank-1.1.0.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.2 Darwin/24.1.0

File hashes

Hashes for ubank-1.1.0.tar.gz
Algorithm Hash digest
SHA256 a5bc6b8b67065f8e32f4760edd1cf3758929df66b1bb8c0255a67090696e2056
MD5 aa0f121421598080efc8409b8c5c7a4a
BLAKE2b-256 e03d46319bf6b8bc885d98da7b6cca7392a467ebff57d8021c84301316a22b39

See more details on using hashes here.

File details

Details for the file ubank-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: ubank-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.2 Darwin/24.1.0

File hashes

Hashes for ubank-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dd63c39935b32080558a99795239e25105ff91265c30c034e26e68f5a85ad6ce
MD5 35586469ac9b18a1760a6c55c581116f
BLAKE2b-256 f45ffb11771fce492f2922e1c8a6127ea571c23ccc52da01f8164c02ea6f38c8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page