fints-rs 0.1.0

Native Rust FinTS 3.0 PinTan client for German online banking
Documentation

fints-rs

crates.io docs.rs

A pure Rust implementation of the FinTS 3.0 (formerly HBCI) banking protocol for German online banking.

Features

  • Full FinTS 3.0 PinTan implementation (two-step and decoupled TAN)
  • Typestate protocol layer — invalid dialog state transitions are compile-time errors
  • Bank-specific workflows (DKB, generic FinTS banks)
  • Built-in registry of 1000+ German banks with FinTS endpoints
  • Account balance, transaction history (MT940), and securities/depot holdings
  • CLI client for interactive banking from the terminal
  • Mock server for integration testing
  • Debug & audit tooling for protocol inspection

Installation

As a library

Add to your Cargo.toml:

[dependencies]
fints-rs = "0.1"

The crate is published as fints-rs on crates.io but the library name is fints, so all imports use use fints::....

CLI client

cargo install fints-rs --features cli

This installs the fints-client binary.

Library Usage

Quick start — DKB

use fints::{dkb, Account, UserId, Pin, ProductId};

#[tokio::main]
async fn main() -> fints::Result<()> {
    // Step 1: Connect and get TAN challenge
    let (session, challenge) = dkb::connect(
        &UserId::new("your_user_id"),
        &Pin::new("your_pin"),
        &ProductId::new("YOUR_PRODUCT_ID"),
        None,
    ).await?;

    println!("Please confirm in your banking app: {}", challenge.challenge);

    // Step 2: After user confirms pushTAN, fetch data
    let account = Account::new("DE12345678901234567890", "BYLADEM1001")?;
    let result = session.fetch(&account, 365).await?;

    println!("Balance: {:?}", result.balance);
    println!("{} transactions", result.transactions.len());
    Ok(())
}

Generic bank access (any FinTS bank)

use fints::{Flow, UserId, Pin, ProductId};

#[tokio::main]
async fn main() -> fints::Result<()> {
    // Step 1: Initiate — pass BLZ to auto-resolve the bank
    let (mut flow, challenge) = Flow::initiate(
        "12030000",  // BLZ (bank code)
        &UserId::new("your_user_id"),
        &Pin::new("your_pin"),
        &ProductId::new("YOUR_PRODUCT_ID"),
        None, None, None,
    ).await?;

    println!("TAN challenge: {}", challenge.challenge);

    // Step 2: After TAN confirmation, fetch balance + transactions
    let result = flow.confirm_and_fetch(
        "DE12345678901234567890",  // IBAN
        "BYLADEM1001",             // BIC
        90,                        // days of history
    ).await?;

    println!("Balance: {:?}", result.balance);
    println!("{} transactions", result.transactions.len());
    println!("{} holdings", result.holdings.len());
    Ok(())
}

Bank lookup

use fints::{all_banks, bank_by_blz};

// Look up a bank by BLZ
if let Some(bank) = bank_by_blz("12030000") {
    println!("{}{}", bank.name, bank.url);
}

// List all known banks
for bank in all_banks() {
    println!("{}: {} ({})", bank.blz, bank.name, bank.url);
}

Low-level protocol access

The typestate Dialog API enforces correct protocol usage at compile time:

use fints::protocol::Dialog;
use fints::types::*;

// Dialog<New> → sync → Dialog<Synced> → open → Dialog<Open> → business ops
// Calling business methods on Dialog<New> won't compile.

States: NewSyncedOpenTanPending → back to Open after TAN.

CLI Usage

First-time setup

fints-client --bank dkb setup
# or by BLZ:
fints-client --bank 12030000 setup

This performs a sync dialog, discovers accounts and TAN methods, and saves a session file for future use.

Sync (balance + transactions + holdings)

fints-client --bank dkb sync
fints-client --bank dkb sync --days 365
fints-client --bank dkb sync --all-accounts

Balance only

fints-client --bank dkb balance
fints-client --bank dkb balance --iban DE12345678901234567890

Transactions

fints-client --bank dkb transactions
fints-client --bank dkb transactions --from 2024-01-01 --to 2024-12-31
fints-client --bank dkb transactions --output json
fints-client --bank dkb transactions --output csv

Holdings (securities/depot)

fints-client --bank dkb holdings

Custom bank (by URL)

fints-client --bank custom --url https://banking.example.de/fints --blz 12345678 sync

Session management

fints-client sessions list
fints-client sessions inspect dkb
fints-client sessions delete dkb

Debug & audit tools

# Inspect bank capabilities
fints-client --bank dkb inspect

# Decode a raw FinTS message
echo "<base64_message>" | fints-client decode --b64

# Audit a bank's protocol compliance
fints-client audit --blz 12030000

Output formats

All data commands support --output human (default), --output json, and --output csv.

Environment variables

Variable Description
FINTS_PRODUCT_ID Override the default FinTS product registration ID
FINTS_SESSION_DIR Override the session storage directory

Global options

--bank <BLZ|name>     Bank identifier (BLZ or shorthand like "dkb")
--user <USER_ID>      FinTS user ID
--pin <PIN>           PIN (prefer interactive prompt instead)
--product-id <ID>     FinTS product registration ID
--verbose / -v        Show decoded FinTS segments
--debug-wire          Show hex wire dumps
--no-persist          Don't save session; print resume token instead
--resume-token <TOK>  Resume from a previously printed token

Architecture

┌─────────────────────────────────────────────────┐
│                    Flow API                     │  ← High-level 2-step TAN flow
├─────────────────────────────────────────────────┤
│                 Workflow layer                  │  ← Bank-specific logic (DKB, Generic)
│            BankOps trait + AnyBank              │
├─────────────────────────────────────────────────┤
│               Protocol layer                   │  ← Typestate Dialog<S> state machine
│     Dialog<New|Synced|Open|TanPending>          │
├──────────────────┬──────────────────────────────┤
│    Segments      │     Message builder          │  ← HKSAL, HKKAZ, HKTAN, ...
├──────────────────┼──────────────────────────────┤
│  Parser          │     Serializer               │  ← Wire format (DEG/DE encoding)
├──────────────────┴──────────────────────────────┤
│              Transport (HTTPS)                  │  ← Base64 over HTTPS POST
└─────────────────────────────────────────────────┘

Feature flags

Feature Description
cli Enables the fints-client binary (clap, rpassword, comfy-table, csv, flate2)
server Enables the fints-server mock server binary (axum)

No features are enabled by default — the library is lightweight with minimal dependencies.

FinTS Product Registration

To use FinTS with German banks in production, you need a registered product ID from the Deutsche Kreditwirtschaft. Set it via:

  • ProductId::new("YOUR_ID") in code
  • --product-id YOUR_ID on the CLI
  • FINTS_PRODUCT_ID=YOUR_ID environment variable

License

MIT