open-banking.io client SDKs
Server-to-server clients 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. These SDKs do the two things an integrator needs — authenticate with your API key and decrypt the data locally with your exported private key — and hand you clean, typed models.
| Language | Package | Path |
|---|---|---|
| .NET |
OpenBankingIO.Client (NuGet) |
dotnet/ |
| Node / TypeScript |
@open-banking-io/client (npm) |
node/ |
| Python |
open-banking-io (PyPI) |
python/ |
| Rust |
open-banking-io (crates.io) |
rust/ |
| Go | github.com/open-banking-io/clients/go |
go/ |
| Java |
io.open-banking:open-banking-io-client (Maven Central) |
java/ |
| Ruby |
open-banking-io (RubyGems) |
ruby/ |
| PHP |
open-banking-io/client (Packagist) |
php/ |
How it works
- In the app, export your credentials bundle (
.json) — it contains yourapiBaseUrl, an API key, and your encryption private key (PKCS#8). - Point an SDK at the bundle. Every request sends
X-Api-Key; every response is decrypted in-process.
// .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}");// Node
const client = OpenBankingClient.fromCredentials("credentials.json");
for (const a of await client.getAccounts())
console.log(a.iban, a.balances.find(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.
The encryption scheme
Each sensitive value is an envelope: version(1) | ephemeralPublicKey(65) | nonce(12) | tag(16) | ciphertext, produced with ephemeral ECDH on P-256 → HKDF-SHA256 (salt = 32 zero bytes, info =
bank.core.ci/zk/v1) → AES-256-GCM. Only your private key can open it. All eight SDKs are verified
against the same fixtures (fixtures/) so they decrypt identically and interoperate with the live
service's wire format.
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/phpunitCI (.github/workflows/ci.yml) builds and tests all eight on every push. Releases are per-package:
each package 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. Targets: NuGet, npm, PyPI, crates.io, Maven Central, RubyGems, Packagist,
and the Go module proxy.
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.