The open-banking.io CLI: a complete guide
The openbanking CLI is the fastest way to work with your bank data from a terminal — list accounts, read statements, sync fresh transactions, and export to CSV or JSON. Everything is zero-knowledge: the service only ever stores ciphertext it cannot read, and your encryption key decrypts each response locally on your machine. The key never touches a server, not even encrypted.
This guide walks through installing the CLI, authenticating, and every command, with real output.
Install
Homebrew (macOS / Linux)
brew install open-banking-io/tap/openbanking
Prebuilt binaries (Windows / macOS / Linux)
Download the archive for your platform from the latest release, unpack it, and put openbanking on your PATH. Windows ships a .zip; macOS/Linux a .tar.gz, each with a checksums.txt.
From source (Go 1.21+)
go install github.com/open-banking-io/clients/cli@latest
Check it works:
$ openbanking version
openbanking 1.0.0
Authenticate
You need a credentials bundle — a small credentials.json you export once from the open-banking.io web app. It contains the API base URL, an API key (ebk_…), and your encryption private key (PKCS#8). Treat it like a password: it is written to disk 0600 and never leaves your machine.
The easy way: login
On a machine with a browser, one command sets up everything:
openbanking login
This runs a localhost loopback + PKCE flow. In the browser you sign in and enter your passphrase; the web app unlocks your P-256 key and hands the full credentials straight back to the CLI's loopback. Flags:
$ openbanking login --help
Usage of login:
-api string
API base URL to log in to (default "https://open-banking.io")
-timeout duration
how long to wait for the browser login (default 3m0s)
Headless / servers: drop the bundle in place
On a box with no browser (CI, a server), export credentials.json from the web app and save it at the CLI's config path — the on-disk format is the exported bundle:
mkdir -p ~/.config/open-banking
cp credentials.json ~/.config/open-banking/credentials.json
chmod 600 ~/.config/open-banking/credentials.json
Or point at any location with an environment variable:
export OPENBANKING_CONFIG=/secrets/openbanking.json
There's also openbanking key import ./credentials.json, which imports only the encryption private key (validated as P-256) onto a machine that already has an API key from login.
Switching environments
Point every command at a different environment (staging, a self-hosted instance) without re-authenticating:
export OPENBANKING_API_BASE_URL=https://staging.open-banking.io
When set, it overrides the API base URL saved in your bundle.
List your accounts
$ openbanking accounts
NAME IBAN TYPE BALANCE CUR BANK ID
USD — CACC — USD Mock ASPSP 4506789c…
Grundkonto DK•• •••• •••• 1555 CACC 111.50 DKK Nordea d60d3fff…
Grundkonto DK•• •••• •••• 7544 CACC -23576.90 DKK Nordea f8d9a25d…
Private Banking konto DK•• •••• •••• 8028 CACC -43218.85 DKK Nordea f1345859…
Onni Hämäläinen — CARD 98.00 EUR Mock ASPSP 2383f8d0…
Oliver Hämäläinen — CACC 17.33 EUR Mock ASPSP cd7cc500…
Aliases: acc, ls. Money is kept as exact decimal strings — never floats — and debits render negative.
Pipe it anywhere with JSON or CSV (JSON is the default when output is piped):
$ openbanking accounts -o json | jq '.[] | {name, balance, currency}'
{
"name": "Grundkonto",
"balance": "111.50",
"currency": "DKK"
}
…
$ openbanking accounts -o csv > accounts.csv
Pick a current account
use remembers a default account so transactions and sync need no id. Pick one interactively with arrow keys, or set it directly:
$ openbanking use cd7cc500-c9bc-456e-8d8d-f1616d98557c
Current account set to Oliver Hämäläinen (cd7cc500…)
The choice is stored in state.json beside your credentials — it is CLI-local and never sent anywhere. An explicit id on a command always overrides it.
Read a statement
With a current account set, just:
$ openbanking transactions
DATE AMOUNT CUR COUNTERPARTY INFO STATUS
2026-06-15 -9.73 EUR Ella Virtanen Ella Virtanen-DBIT-9.73-r4i1r BOOK
2026-06-15 -3.40 EUR Ella Korhonen Ella Korhonen-DBIT-3.40-m3172 BOOK
2026-06-15 0.13 EUR Aino Nieminen Aino Nieminen-CRDT-0.13-hxqjw BOOK
2026-06-15 0.57 EUR Aino Mäkinen Aino Mäkinen-CRDT-0.57-y7z4v BOOK
2026-06-15 3.79 EUR Onni Korhonen Onni Korhonen-CRDT-3.79-pfl06 BOOK
8 shown, 8 total
Alias: tx. Pass an id for any account and filter by date or page through results:
$ openbanking transactions --help
Usage of transactions:
-from string earliest booking date (YYYY-MM-DD)
-to string latest booking date (YYYY-MM-DD)
-limit int max rows to return (0 = server default)
-offset int rows to skip
$ openbanking transactions cd7cc500… --from 2025-01-01 --limit 3 -o csv
DATE,AMOUNT,CUR,COUNTERPARTY,INFO,STATUS
2026-06-15,-9.73,EUR,Ella Virtanen,Ella Virtanen-DBIT-9.73-r4i1r,BOOK
2026-06-15,-3.40,EUR,Ella Korhonen,Ella Korhonen-DBIT-3.40-m3172,BOOK
2026-06-15,0.13,EUR,Aino Nieminen,Aino Nieminen-CRDT-0.13-hxqjw,BOOK
The JSON shape carries a stable transaction id alongside each row, ready for a database or a reconciliation script:
$ openbanking transactions cd7cc500… --limit 1 -o json
{
"items": [
{
"id": "c1cb427d-3e2c-4c81-993e-21ef179a7c9d",
"date": "2026-06-15",
"amount": "-9.73",
"currency": "EUR",
"counterparty": "Ella Virtanen",
"info": "Ella Virtanen-DBIT-9.73-r4i1r",
"status": "BOOK"
}
],
"shown": 1,
"total": 8
}
Pull fresh transactions
sync fetches the latest transactions from the bank for one account (the current one, or an id you pass):
$ openbanking sync
Synced: 0 new transaction(s) (3 fetched)
Sync is incremental and idempotent — it only inserts rows you don't already have, so re-running is always safe. Do every connected account at once:
$ openbanking sync --all
Synced 3 account(s): 0 new transaction(s)
Your bank connections
$ openbanking connections
BANK COUNTRY STATUS ACCOUNTS PSU VALID UNTIL LAST SYNCED SESSION
Mock ASPSP DK Active 1 personal 2026-10-01T18:41:33Z 2026-07-04T16:00:12Z c5cb2c9d…
Nordea DK RequiresReauth 3 personal 2026-09-15T12:22:22Z 2026-06-17T13:22:18Z 4327bcad…
Mock ASPSP DK Active 2 personal 2026-09-14T18:49:52Z 2026-07-03T18:45:19Z 701bcce3…
Alias: conn. A RequiresReauth status means the bank's consent has lapsed and you need to reconnect it in the web app before it will sync again.
Which banks can I connect?
$ openbanking banks --country DK
NAME COUNTRY BIC PSU TYPES BETA
Nordea DK NDEADKKK personal
Nordea Corporate DK NDEADKKK business beta
Vestjysk Bank DK VEHODK22 business,personal
Mock ASPSP DK — business,personal
Saxo Bank DK SAXODKKKXXX business,personal beta
Nordea First Card DK NDEADKKK business
Connecting a new bank happens in the web app — it needs an interactive consent redirect — so the CLI has no
connectcommand. It reads and syncs the connections you already have.
Output formats, color, and completion
Every listing command takes a global -o/--output:
openbanking accounts -o table # pretty table (default in a terminal)
openbanking accounts -o json # json (default when piped)
openbanking transactions -o csv # csv for spreadsheets
Color is on for terminals and off when piped; force it off with --no-color or the NO_COLOR environment variable.
Shell completion is one line in your rc file (also bash, fish):
source <(openbanking completion zsh)
Run openbanking with no arguments in a terminal for an interactive menu that walks through the same commands.
How the zero-knowledge model works
login establishes trust in the browser and hands the CLI two things: an API key (sent as X-Api-Key on every request) and your encryption private key. Each response from the service is an opaque ciphertext envelope; the CLI decrypts it in-process with your key using ECDH-P256 → HKDF-SHA256 → AES-256-GCM.
The server only ever holds your public key. It cannot read your account names, balances, or transactions — only you can, on your machine. That is why connecting a bank and unlocking your key both happen in the browser, and why the CLI keeps credentials.json at 0600.
Troubleshooting
no credentials at … — run openbanking login first— the config file is missing. Runopenbanking login, or drop your exportedcredentials.jsonat~/.config/open-banking/credentials.json(or$OPENBANKING_CONFIG).- A connection shows
RequiresReauth— the bank consent expired; reconnect it in the web app, thensyncagain. syncreturns 0 new but you expected data — the account is already up to date, or its connection isn'tActive. Checkopenbanking connections.- Wrong environment — set
OPENBANKING_API_BASE_URLto point at staging or a self-hosted instance without re-runninglogin.
Where to go next
The CLI is built on the same open-source SDKs available for .NET, Node, Python, Rust, Go, Java, Ruby, and PHP — so anything you can do here, you can script in your language of choice. Grab your credentials bundle at open-banking.io and start reading your data in minutes.