Open Source
2026-03

Inoffizielle Scalable Capital API – Portfoliodaten via REST & SSE

Scalable Capital hat keine öffentliche API. Also habe ich mir einen lokalen Proxy gebaut, der Portfoliodaten per REST und SSE bereitstellt: Bewertungen, Kurse, Transaktionen und Live-Streams.

TypeScriptNode.jsPuppeteerGraphQLSSE
Inoffizielle Scalable Capital API – Portfoliodaten via REST & SSE preview

Ich investiere über Scalable Capital und wollte meine Portfoliodaten in einem eigenen Dashboard zusammenführen. Eine öffentliche API gibt es nicht, also habe ich mir einen lokalen Proxy gebaut.

Das Login-Problem

Das erste Hindernis war die Authentifizierung. Credentials hardcoden kam nicht in Frage, und das Login-Formular zu scrapen wäre beim nächsten Frontend-Update gebrochen.

Die Lösung: Puppeteer öffnet ein echtes Chromium-Fenster, ich logge mich selbst ein inklusive 2FA, und das Skript wartet, bis die SPA vollständig geladen ist. Aus dem authentifizierten Browser-State extrahiert es Session-Cookies, Portfolio-ID und weitere IDs, die für die späteren API-Calls nötig sind.

Die Session wird auf Disk gespeichert und beim nächsten Server-Start wiederhergestellt, ein Neustart erzwingt also kein erneutes Login. Antwortet ein Request mit 401 oder 403, wird der Login-Flow automatisch neu gestartet und der Request einmalig wiederholt.

Die eigentliche API

Die Scalable Capital App kommuniziert intern mit einem privaten GraphQL-Endpunkt. Echtzeit-Daten laufen über einen WebSocket mit dem graphql-transport-ws-Protokoll.

Das Protokoll habe ich manuell implementiert statt eine fertige Client-Library zu nutzen, damit die Reconnect- und Subscription-Logik transparent bleibt.

WebSocket-Singleton und SSE-Bridge

Eine einzelne WebSocket-Verbindung zum Upstream wird von allen verbundenen SSE-Clients geteilt. Die Verbindung wird beim ersten Client aufgebaut und beim letzten wieder abgebaut.

[SSE-Client 1] ──┐
[SSE-Client 2] ──┤── SubscriptionManager ── einzelne WS-Sub ── Upstream WS
[SSE-Client N] ──┘

Für Kurs-Streams verwaltet der QuoteManager die Vereinigungsmenge aller angeforderten ISINs. Kommt ein neuer Client mit anderen ISINs dazu, wird die Upstream-Subscription aktualisiert und jeder eingehende Tick vor der Weiterleitung pro Client gefiltert.

REST-Clients bekommen das transparent: GET /portfolio gibt einen gecacheten WebSocket-Tick zurück, wenn er frisch genug ist, und wartet sonst kurz auf die nächste Nachricht.

Endpunkte

Auth

  • POST /auth/login, GET /auth/status, DELETE /auth/logout

Portfolio

  • GET /portfolio – aktuelle Bewertung
  • GET /portfolio/inventory – Positionen und Sparpläne
  • GET /portfolio/cash – Kaufkraft und Auszahlungskraft
  • GET /portfolio/timeseries – zeitgewichtete Rendite
  • weitere: /watchlist, /interest-rates, /pending-orders

Wertpapiere

  • GET /securities/:isin – Details mit Live-Kurs
  • GET /securities/:isin/timeseries – Kurshistorie
  • weitere: /tick, /tradability, /buyable

Transaktionen und Tagesgeld

  • GET /transactions – paginiert, filterbar nach ISIN, Typ und Status
  • GET /savings, GET /savings/transactions

Streaming

  • GET /valuation/stream – SSE mit Live-Portfolio-Bewertung
  • GET /quotes/stream?isins=ISIN1,ISIN2 – SSE mit Live-Kursen

Sonstiges

  • POST /proxy – roher GraphQL-Durchgriff
  • GET /docs – Scalar-UI aus der OpenAPI-Spec

API-Änderungserkennung

Mit dem --monitor-Flag lässt sich Drift-Detection aktivieren. Das Tool vergleicht bei jeder Antwort die Struktur des Payloads gegen eine gespeicherte Baseline und schreibt Änderungen (neue oder fehlende Felder, Typwechsel) mit Zeitstempel in eine separate Datei. So fällt schnell auf, wenn Scalable Capital ihre interne API anpasst.

Sicherheit

Der Server bindet nur an localhost und ist damit nicht im Netzwerk erreichbar. Optional lässt sich ein Token-Header für alle Routen erzwingen. Die Session-Datei ist gitignored und wird mit restriktiven Dateirechten geschrieben.


Kein offizielles Projekt, keine Verbindung zu Scalable Capital. Nutzung auf eigene Verantwortung.