# comdirect-rest-api
High-availability Rust client for the comdirect REST API.
This crate provides:
- Typed API access for `accounts` and `brokerage` endpoints
- Session lifecycle orchestration (`login`, `try_restore`, `shutdown`)
- Automatic token refresh with state and refresh-token callbacks
- Retry and infrastructure helpers for resilient API calls
- Optional web-based interactive TAN flow via the `web` feature
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
comdirect-rest-api = "0.2.0"
```
Enable web login routes when needed:
```toml
[dependencies]
comdirect-rest-api = { version = "0.2.0", features = ["web"] }
```
## Quick Start
### 1. Restore an existing session (recommended for services)
```rust
use comdirect_rest_api::{Session, SessionConfig};
async fn run() -> Result<(), comdirect_rest_api::ComdirectError> {
let config = SessionConfig::new("client-id", "client-secret", "username", "pin")
.with_base_url("https://api.comdirect.de")
.with_request_timeout(std::time::Duration::from_secs(20))
.with_refresh_buffer(std::time::Duration::from_secs(90));
let session = Session::from_config(config)?;
session.try_restore("persisted-refresh-token").await?;
let balances = session.accounts().get_balances().await?;
println!("{} accounts", balances.values.len());
session.shutdown().await;
Ok(())
}
```
### 2. Interactive login flow
```rust
use comdirect_rest_api::{Session, TanAction};
use std::io::{self, Write};
async fn run() -> Result<(), comdirect_rest_api::ComdirectError> {
let session = Session::new("client-id", "client-secret", "username", "pin")?;
session
.set_refresh_token_callback(|refresh_token| {
// Persist this token securely and use try_restore() on next startup.
println!("new refresh token: {refresh_token}");
})
.await;
session
.login(|challenge| async move {
println!("challenge {}", challenge.challenge_id);
println!("Please approve the Push-TAN in the Comdirect app.");
print!("Press Enter only after you have approved it... ");
let _ = io::stdout().flush();
let mut line = String::new();
let _ = io::stdin().read_line(&mut line);
TanAction::ConfirmPushTan
})
.await?;
session.shutdown().await;
Ok(())
}
```
Important: comdirect does not provide a redirect-based completion step for this TAN flow.
Your application callback must wait for an explicit user confirmation signal (for example a
frontend button like "I've allowed it") before returning `TanAction::ConfirmPushTan`.
## API Surface
Top-level modules:
- `session`: auth lifecycle, restore/login flow, refresh worker integration
- `accounts`: typed account endpoints (balances, single balance, transactions)
- `brokerage`: typed brokerage endpoints (depots, positions, instruments)
- `auth`, `types`, `error`: shared auth models, common types, and error handling
- `web` (feature-gated): mounts browser-driven auth routes for TAN workflows
## Optional Web Feature
When `web` is enabled, you can expose login routes with Axum.
- `Session::login_web(...)` mounts default auth routes under `/comdirect`
- `mount_session_login_route(...)` allows custom route mounting
- The callback must still wait for explicit user confirmation before submitting `ConfirmPushTan`
## Development
Run tests for this crate:
```bash
cargo test -p comdirect-rest-api
```
Run with optional web feature tests/build:
```bash
cargo test -p comdirect-rest-api --features web
```
## License
Licensed under either:
- MIT
- Apache-2.0
at your option.