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 connect command. 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. Run openbanking login, or drop your exported credentials.json at ~/.config/open-banking/credentials.json (or $OPENBANKING_CONFIG).
  • A connection shows RequiresReauth — the bank consent expired; reconnect it in the web app, then sync again.
  • sync returns 0 new but you expected data — the account is already up to date, or its connection isn't Active. Check openbanking connections.
  • Wrong environment — set OPENBANKING_API_BASE_URL to point at staging or a self-hosted instance without re-running login.

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.