geldstrom
Pure-Python FinTS 3.0 client for German banking. Handles protocol parsing, dialog management, decoupled TAN (SecureGo+, pushTAN, …), and exposes a synchronous API for reading accounts, balances, and transaction history.
Package layout
geldstrom/
├── clients/
│ ├── base.py # BankClient protocol
│ ├── fints3.py # FinTS3Client — blocking, context-manager
│ └── fints3_decoupled.py # FinTS3ClientDecoupled + PollResult
├── domain/
│ └── model/
│ ├── accounts.py # Account, AccountOwner, AccountCapabilities
│ ├── balances.py # BalanceSnapshot, BalanceAmount
│ ├── bank.py # BankRoute, BankCapabilities, BankCredentials
│ └── transactions.py # TransactionEntry, TransactionFeed
└── infrastructure/
└── fints/
├── challenge/ # Challenge, ChallengeHandler, TANConfig,
│ # DecoupledTANPending, DetachingChallengeHandler
├── credentials.py # GatewayCredentials (FinTS connection bundle)
├── dialog/ # Wire-level FinTS dialog (connection, security,
│ # message, responses, TAN strategies)
├── exceptions.py # FinTSClientPINError, FinTSConnectionError, …
├── operations/ # FinTS operations (accounts, balances,
│ └── transactions/ # transactions: mt940, camt, feed pipelines)
├── protocol/ # Tokenizer, parser, segment/DEG definitions
├── services/ # High-level service objects used by clients
│ # (FinTSAccountService, FinTSBalanceService,
│ # FinTSTransactionService, FinTSMetadataService)
├── session.py # FinTSSessionState, SessionToken protocol
├── support/ # FinTSConnectionHelper, serialization helpers
└── tan.py # TANMethod value object
Quick start
from geldstrom import FinTS3Client
with FinTS3Client(
bank_code="12345678",
server_url="https://banking.example.com/fints",
user_id="your_user",
pin="your_pin",
product_id="YOUR_PRODUCT_ID",
tan_method="946", # required by most banks even for read-only ops
) as client:
accounts = client.list_accounts()
balance = client.get_balance(accounts[0])
feed = client.get_transactions(accounts[0])
Clients
FinTS3Client
Standard blocking client. Call connect() (or use as a context manager) to open a dialog and discover accounts. Subsequent method calls reuse the cached session. Use session_state to persist the session across process restarts.
FinTS3ClientDecoupled
Subclass of FinTS3Client that raises DecoupledTANPending instead of blocking when the bank requires an app-based confirmation. The live connection context is kept alive internally; call poll_tan() in a loop until status == "approved". The gateway uses this variant for all requests.
from geldstrom import FinTS3ClientDecoupled, DecoupledTANPending
client = FinTS3ClientDecoupled(...)
try:
feed = client.get_transactions(account)
except DecoupledTANPending:
while True:
result = client.poll_tan()
if result.status == "approved":
feed = result.data
break
elif result.status == "pending":
time.sleep(2)
else:
raise RuntimeError(result.error)
TAN handling
Most German banks require a TAN (2FA) even for read-only operations.
- Pass
tan_method(e.g."946"for SecureGo+/decoupled TAN) to avoid a runtime warning. - Call
client.get_tan_methods()to discover all methods advertised by the bank; this performs a lightweight sync dialog that does not require a TAN. TANConfigcontrols polling behaviour (poll_interval,timeout_seconds).ChallengeHandleris a protocol for custom challenge presentation — the defaultDetachingChallengeHandlerraisesDecoupledTANPendingfor decoupled challenges.
Session persistence
FinTS3Client.session_state returns a FinTSSessionState after connect(). Serialize it with .serialize() and reconstruct with FinTSSessionState.deserialize(data). Pass the reconstructed state as session_state=... to skip the initial sync dialog on subsequent runs.
Examples
See examples/ in the repository root for runnable demos (account listing, balance fetching, transaction history, TAN flow walkthrough).
Metadata
Release files for geldstrom 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geldstrom-0.1.5.tar.gz | 85.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geldstrom-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 213.8 kB
Release files / geldstrom-0.1.5.tar.gz
| Download URL | geldstrom-0.1.5.tar.gz |
|---|---|
| Size | 85.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
af107fa381c12b9995da03b0b881e86d9b11b109829369ece7bb9a7a2bbf6c57
|
|
BLAKE2b-256 checksum How to use checksums |
64c2f34567f41c2bd13df63538b6f3e3745ce8b7414d34b83a51eecef6034a3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.
Transparency logRelease files / geldstrom-0.1.5-py3-none-any.whl
| Download URL | geldstrom-0.1.5-py3-none-any.whl |
|---|---|
| Size | 127.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec498a3fdfeee328dbfeaa503471ad56780398b833eb07447144d00131caa19a
|
|
BLAKE2b-256 checksum How to use checksums |
d759e9e5f8d0d18e3ac001edf3329cd1eb0a73443bb83cee4c3a00b132287322
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.
Transparency log