Skip to content

open-banking-io/clients

open-banking.io

open-banking.io client SDKs

CI Semgrep Gitleaks OpenSSF Scorecard OpenSSF Best Practices codecov License: MIT

Official server-to-server SDKs for open-banking.io in .NET, Node, Python, Rust, Go, Java, Ruby, and PHP.

open-banking.io is zero-knowledge: the service stores and returns only ciphertext it cannot read. Each SDK does the two things an integrator needs — authenticate with your API key and decrypt your data locally with your private key — and hands you clean, typed models.

New here? Create an account and export your credentials bundle at open-banking.io, then pick your language below.

Pick your language

Each package has its own README with install instructions, a runnable example, and language-specific notes (money types, async, dependencies).

Language Package Version Guide
.NET OpenBankingIO.Client (NuGet) NuGet dotnet/
Node / TypeScript @open-banking-io/client (npm) npm node/
Python open-banking-io (PyPI) PyPI python/
Rust open-banking-io (crates.io) crates.io rust/
Go github.com/open-banking-io/clients/go Go Reference go/
Java io.open-banking:open-banking-io-client (Maven Central) Maven Central java/
Ruby open-banking-io (RubyGems) Gem ruby/
PHP open-banking-io/client (Packagist) Packagist php/

Prefer the terminal? There's also a command-line client (openbanking).

Getting started

  1. Get your credentials. In the open-banking.io app, export your credentials bundle (credentials.json) — it contains your apiBaseUrl, an API key, and your encryption private key (PKCS#8).
  2. Point an SDK at the bundle. Every request sends X-Api-Key; every response is decrypted in-process with your private key. The service never sees your plaintext data.
// Node / TypeScript — the same shape exists in all eight languages (see each guide above).
import { OpenBankingClient } from "@open-banking-io/client";

const client = OpenBankingClient.fromCredentials("credentials.json");
for (const a of await client.getAccounts()) {
  const booked = a.balances.find((b) => b.type === "ITBD");
  console.log(`${a.iban}: ${booked?.amount} ${a.currency}`);
}
The same example in .NET, Python, Rust, Go, Java, Ruby, and PHP
// .NET
using var client = OpenBankingClient.FromCredentials("credentials.json");
foreach (var a in await client.GetAccountsAsync())
    Console.WriteLine($"{a.Iban}: {a.Balances.First(b => b.Type == "ITBD").Amount} {a.Currency}");
# Python
client = OpenBankingClient.from_credentials("credentials.json")
for a in client.get_accounts():
    booked = next(b for b in a.balances if b.type == "ITBD")
    print(a.iban, booked.amount, a.currency)
// Rust
let client = OpenBankingClient::from_credentials("credentials.json")?;
for a in client.get_accounts()? {
    let booked = a.balances.iter().find(|b| b.type_ == "ITBD");
    println!("{:?} {:?} {}", a.iban, booked.map(|b| &b.amount), a.currency);
}
// Go
client, _ := openbanking.FromCredentials("credentials.json", nil)
accounts, _ := client.GetAccounts()
for _, a := range accounts {
    for _, b := range a.Balances {
        if b.Type == "ITBD" { fmt.Println(a.Iban, b.Amount, a.Currency) }
    }
}
// Java
var client = OpenBankingClient.fromCredentials("credentials.json");
for (Account a : client.getAccounts())
    a.balances().stream().filter(b -> b.type().equals("ITBD")).findFirst()
        .ifPresent(b -> System.out.println(a.iban() + " " + b.amount() + " " + a.currency()));
# Ruby
client = OpenBankingIO::Client.from_credentials("credentials.json")
client.get_accounts.each do |a|
  booked = a.balances.find { |b| b.type == "ITBD" }
  puts "#{a.iban} #{booked&.amount} #{a.currency}"
end
// PHP
$client = OpenBankingIO\Client::fromCredentials("credentials.json");
foreach ($client->getAccounts() as $a) {
    foreach ($a->balances as $b) {
        if ($b->type === "ITBD") echo "{$a->iban} {$b->amount} {$a->currency}\n";
    }
}

All eight expose the same surface — getAccounts, getTransactions(accountId, …), getConnections, sync(accountId), syncAll(). sync decrypts the account's session uid locally and posts it, so the service can refresh from the bank without ever holding it in plaintext.

How it works

  1. Your bank credentials are never sent to open-banking.io.
  2. Your account data (IBAN, balances, transactions) is stored encrypted by the service.
  3. Only your local private key can decrypt it — the service holds ciphertext it cannot read.

Each sensitive value is an envelope sealed with ephemeral ECDH (P-256) → HKDF-SHA256 → AES-256-GCM; only your private key can open it, and all eight SDKs are verified against the same fixtures/ so they decrypt identically. The full wire format, trust boundaries, and assumptions are in THREAT_MODEL.md.

Development

# regenerate the shared test fixtures (keypair + encrypted sample responses)
node tools/generate-fixtures.mjs

# run each SDK's tests (crypto round-trip + a mock-server integration suite)
dotnet test dotnet/
cd node   && npm install && npm test
cd python && pip install -e .[dev] && pytest -q
cd rust   && cargo test
cd go     && go test ./...
cd java   && mvn -B verify
cd ruby   && bundle install && bundle exec rspec
cd php    && composer install && vendor/bin/phpunit

CI builds and tests all eight on every push. Releases are per-package — each publishes from its own <dir>/vX.Y.Z tag (e.g. node/v0.2.0), so tagging one package never republishes the others. Cut a release from Actions → Release (pick a package + version); see RELEASING.md.

Security & contributing

Zero-knowledge security model and trust boundaries: THREAT_MODEL.md. Report vulnerabilities privately per SECURITY.md. Contributions welcome — see CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SUPPORT.md.

MIT licensed.

About

Zero-knowledge open banking — server-to-server SDKs (.NET, Node, Python, Rust, Go, Java, Ruby, PHP) and the openbanking CLI for open-banking.io

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors