Der Daemon bietet eine REST-API unter /api und einen WebSocket unter /ws. Beide gehören zur selben Sitzung: Du meldest dich mit einem Cookie an, sendest bei jedem Schreibzugriff einen CSRF-Header und abonnierst Topics für Live-Daten. Das OpenAPI-Dokument wird aus dem Code generiert und ist die Quelle des TypeScript-Clients.
Das OpenAPI-Dokument ist packages/api-client/openapi.json (“Pithyx API”, Version v1). Ein laufender Daemon liefert es anonym unter GET /api/openapi.json aus. Es gibt kein Präfix /api/v1. Die Endpunkte sind nach Tags gruppiert: App API, Apps, Auth, Desktop, FileServices, Files, Installer, Jobs, Logs, Notifications, Permissions, Setup, Shares, Storage, Store, System und Users. Siehe die API-Referenz.
Nicht Teil des OpenAPI-Dokuments: der WebSocket unter /ws, WebDAV unter /webdav/, die App-Frontends und der Backend-Proxy unter /apps/<id>/ sowie die statischen Dateien des Desktops.
Konventionen:
- JSON nutzt camelCase, Enums sind Strings, und alle Eigenschaften sind immer vorhanden (nullable als
null). - Daten sind ISO 8601 in UTC.
- Jede Antwort hat einen
X-Request-Id-Header. Fehler sind Problem Details nach RFC 9457; siehe Fehler, Tracing und Logging. GET /api/healthist anonym und liefert{ "status": "ok", "mode": ... }.- Aktualisierungen von Layout und Desktop-Elementen nutzen optimistische Nebenläufigkeit mit
If-Match. - Statistik-Topics sind auf 1 Hz gedrosselt.
Apps nutzen eine eigene Oberfläche, /api/app/**, die nur Host-Tokens von Apps akzeptiert, nie das Sitzungs-Cookie. Siehe Apps im Überblick.
Authentifizierung und CSRF
Abschnitt betitelt „Authentifizierung und CSRF“POST /api/auth/loginliefert den Benutzer oder eine Zwei-Faktor-Challenge, die 5 Minuten gültig ist.POST /api/auth/login/totpschließt die Challenge mit einem Code der Authenticator-App oder einem Wiederherstellungscode ab.- Die Antwort setzt das Cookie
pithyx_session(HttpOnly,SameSite=Strict, Pfad/). Das FlagSecurewird nur gesetzt, wenn die Anfrage selbst HTTPS nutzt, weil reines HTTP per Adresse funktionieren muss.
Der Server speichert nur den SHA-256 des Sitzungs-Tokens. Eine Sitzung läuft nach 7 Tagen ohne Nutzung oder insgesamt nach 30 Tagen ab. Ein offener WebSocket hält sie am Leben und wird stündlich geprüft.
Jede Anfrage unter /api, die nicht GET, HEAD oder OPTIONS ist, muss den Header X-Pithyx-Request: 1 tragen, auch die Anmeldung. Ohne ihn antwortet der Daemon mit auth.csrf.header_missing. Eine abgelaufene oder fehlende Sitzung ergibt 401 auth.session.expired.
Nur fehlgeschlagene Anmeldeversuche zählen für das Rate-Limit: 5 pro Client-Adresse und Benutzername und 30 pro Client-Adresse in einem festen Fenster von 5 Minuten. Die Antwort ist 429 auth.rate.limited mit einem Retry-After-Header. Derselbe Limiter schützt die Dateiprotokolle.
Passwörter nutzen Argon2id (64 MiB, 3 Durchgänge) und brauchen mindestens 8 Zeichen. Pithyx hat keine persönlichen Zugriffs-Tokens für Skripte; ein Skript meldet sich an wie der Desktop. Passkeys sind nicht gebaut.
WebSocket und Topics
Abschnitt betitelt „WebSocket und Topics“GET /ws stuft eine authentifizierte Anfrage auf einen WebSocket hoch. Der Origin eines Browsers muss zum Host passen, sonst schließt der Daemon mit 4403; Clients ohne Origin-Header werden akzeptiert.
Client-Nachrichten sind sub und unsub mit einer ID und einem Topic. Der Server antwortet mit ack, dann snap (der vollständige Zustand, einmal) und event (Änderungen), oder mit error und einem Code. Die größte Client-Nachricht ist 16 KB. Ein Client, der nicht mitkommt (Ausgangspuffer von 256 Nachrichten), wird mit 1008 geschlossen.
| Close-Code | Bedeutung | Aktion des Clients |
|---|---|---|
| 1000 | Normales Schließen | keine |
| 1001 | Daemon-Neustart | neu verbinden |
| 1008 | Client zu langsam | neu verbinden |
| 1009 | Nachricht zu groß | neu verbinden |
| 4401 | Sitzung beendet | Anmeldung anzeigen |
| 4403 | Verboten | anhalten |
Topic-Muster dürfen + für eine Ebene und # für den Rest nutzen. Berechtigungen werden für jeden Snapshot und jedes Ereignis geprüft. Topics heute: system/info, system/resources, system/processes, system/network, system/updates, storage/disks, storage/pools, storage/alerts, shares/list, jobs, jobs/+, notifications, session/permissions, files/+/+, thumbnails/+/+, apps, apps/admin, apps/+/context und store/admin.
Generierter Client
Abschnitt betitelt „Generierter Client“Das Paket @pithyx/api-client (privat, nicht veröffentlicht) wird aus dem OpenAPI-Dokument generiert. Beim Bauen des Daemons entsteht openapi.json; pnpm generate erzeugt dann src/generated/schema.ts, error-codes.ts und close-codes.ts sowie die Manifest-Typen des SDK neu. Bearbeite generierte Dateien nie; bei einem Merge-Konflikt nimmst du eine Seite und generierst neu. pnpm check:repo schlägt fehl, wenn sie veraltet sind.
Der Client umhüllt openapi-fetch, fügt den CSRF-Header hinzu und wirft PithyxApiError (Status, Code, Parameter, Request-ID).
Stabilität
Abschnitt betitelt „Stabilität“Die REST- und WebSocket-API, die SDK-API, das Manifest-Schema und die Fehlercodes sind stabile Verträge: Eine inkompatible Änderung braucht eine Major-Version. Sie folgen ab 1.0.0 SemVer.