comdirect-rest-api 0.2.1

High-availability Rust client for the comdirect REST API
Documentation

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:

[dependencies]
comdirect-rest-api = "0.2.0"

Enable web login routes when needed:

[dependencies]
comdirect-rest-api = { version = "0.2.0", features = ["web"] }

Quick Start

1. Restore an existing session (recommended for services)

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

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:

cargo test -p comdirect-rest-api

Run with optional web feature tests/build:

cargo test -p comdirect-rest-api --features web

License

Licensed under either:

  • MIT
  • Apache-2.0

at your option.