Files
MindSift/Doku/api/rest.md
T
sandrodachandClaude Opus 5.5 bcc06da3ee
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m6s
fix(realtime): scope events to authorized users, authorize rooms, keep SSE alive
Phase 0 of the collaboration plan:
- Remove BroadcastToAll; task, task list and workspace folder events now
  only reach users who can see the resource. Task list events carry only
  the list ID, clients reload with their own permissions.
- Reject unauthenticated WebSocket/SSE connections (401). Every room join
  (URL room, JOIN_ROOM, SSE rooms) is checked via a room authorizer;
  /events/rooms requires login and only accepts the caller's own sseId.
- Reorder rejects tasks the caller cannot access or edit (IDOR).
- Lift the server WriteTimeout for SSE streams so they are not cut after 30s.
- Fix folder share removal sending DOC_DELETED to the share ID.
- Tests for all of the above; docs and flaw list updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:19:14 +01:00

8.1 KiB
Raw Blame History

REST-API

Basis: /api/v1. Antworten sind JSON; Fehler haben die Form {"error": "Text"}. Authentifizierung über Authorization: Bearer <JWT> oder Bearer mindsift_sec_… bzw. Header X-API-Key. Zeitstempel sind ISO-8601 (UTC). Quelle der Wahrheit sind die Routen in server.go.

Öffentlich

Methode Pfad Zweck
GET /health Lebenszeichen
GET /auth/status needsSetup, allowRegistration, instanceName, demoMode
POST /auth/setup Erstes Administratorkonto (email, password, displayName, instanceName, allowRegistration, sharingMode, seedSampleData); nur solange es keine Konten gibt
POST /auth/register Registrierung (email, password, displayName, inviteCode); nur mit Code oder wenn freigegeben
POST /auth/login Anmeldung (login/email/username, password) → {token, user}
POST /auth/quickstart Immer 403 (Gastzugang deaktiviert)
POST /webhooks/ingest Aufgabe per Webhook anlegen, Token als ?token=, X-API-Key oder Bearer. Body: title/content/text/message, priority, source, tags, dueDate; Klartext-Body wird als Inhalt genommen
GET /ws, /ws/spaces/{id}, /ws/lists/{id} WebSocket, siehe websocket.md; Token als ?token= nötig
GET /events SSE-Fallback; Token als ?token= nötig

Konto und Allgemeines (angemeldet)

Methode Pfad Zweck
GET /auth/me Benutzer und Kennzahlen
POST /events/rooms SSE-Raum beitreten/verlassen (sseId, room, action); nur eigene sseId, nur Räume mit Lesezugriff
POST /auth/logout Token sperren
POST /auth/revoke-all Alle Sitzungen beenden (token_version +1)
PATCH /auth/settings displayName, email, password, avatarUrl, alarmChannels, alarmEmail, discordWebhookUrl, customWebhookUrl, notifyBeforeMinutes
POST /auth/alarms/test Test-Alarm (channel: email/discord/webhook, optional target)
GET /users/directory, /collaborators Benutzerverzeichnis für Freigaben (FLAW-10)
GET /stats Zähler fürs Dashboard
GET /search?q= Suche in eigenen Gedanken und Notizen
GET /export Datenexport als JSON
GET/POST/DELETE /keys, /keys/{id} API-Keys verwalten (Klartext nur bei Erstellung)

Gedanken, Triage, Aufgaben

Methode Pfad Zweck
POST /inbox Schnellerfassung. Body: content, priority, source, dueDate, target (inbox/task/list_item/document), targetListId, taskListId (snake_case-Varianten werden akzeptiert)
GET /thoughts?status= Gedanken (inbox, kept, converted, discarded, all)
GET/PATCH/DELETE /thoughts/{id} Einzelabruf; Teiländerung (content, isCompleted, dueDate, priority, taskListId, kanbanStatus, notes, subtasks, tags); Löschen
DELETE /thoughts/discarded/purge Papierkorb leeren
GET /triage/deck Posteingang (max. 100)
PATCH /triage/{id} action: keep/discard/restore; mit convertTo: task/document/list_item
GET /tasks?taskListId= Aufgaben (optional einer Liste)
POST /tasks/reorder, /task-lists/{id}/tasks/reorder Reihenfolge/Spalte ändern (items[{id, sortOrder, kanbanStatus}])
POST /tasks/{id}/unlink Verknüpfung zu Notiz-Block lösen

Aufgabenlisten

Methode Pfad Zweck
GET/POST /task-lists Listen (permission je Liste: owner/editor/viewer); anlegen (title, icon, color, teamId)
PUT/DELETE /task-lists/{id} Ändern (title, icon, color, teamId, columns) – nicht für Leser; Löschen nur Eigentümer
GET /task-lists/{id}/shares Freigaben
POST /task-lists/{id}/shares Nur Eigentümer. Body: targetType (team/user), targetId, permission (editor/viewer, Standard editor). Erneutes Senden für dasselbe Ziel ändert die Stufe
DELETE /task-lists/{id}/shares/{shareId} Nur Eigentümer

Schreibzugriffe von Lesern auf Listen oder deren Aufgaben liefern 403 („Keine Schreibrechte für diese Aufgabenliste (nur Lesen)“).

Workspace

Methode Pfad Zweck
GET/POST/DELETE /folders Ordnerliste, anlegen (path), löschen
POST /folders/move sourcePath, targetParentPath
GET/POST /workspace/folders/shared Geteilte Ordner; anlegen (name, mountPath)
GET/DELETE /workspace/folders/shared/{id} Abruf; Löschen
PUT /workspace/folders/shared/{id}/mount Eigenen Einhängepfad ändern (mountPath)
GET/POST/DELETE /workspace/folders/shared/{id}/shares[/{shareId}] Freigaben (nur Lesen wirksam)
GET /workspace/tags, /workspace/tags/{tag} Tag-Übersicht und -Details
PUT /workspace/tags/{tag}/note Tag-Seite speichern (content)
GET/POST /documents Notizen auflisten; anlegen (title, icon, folderPath, blocks, tags, isPinned)
GET/PUT/DELETE /documents/{id} Abruf; Ändern (title, icon, folderPath, blocks, tags, isPinned); Löschen
PATCH /documents/{id}/blocks Teil-Update der Blöcke (upserted, deletedIds, Reihenfolge); löst DOC_BLOCKS_PATCHED aus
PUT /documents/{id}/move Ordner wechseln (folderPath)
POST /documents/{id}/blocks/{blockId}/enhanced-task Aus einem Block eine verknüpfte Aufgabe machen (content, checked)
GET/POST/DELETE /documents/{id}/shares[/{userId}] Notiz-Freigaben (userId/email/teamId; wirksam nur Lesen)

Nur der Eigentümer schreibt in eine Notiz; Empfänger erhalten 403/„nur Lesezugriff“ (FLAW-17).

Geteilte Listen

Methode Pfad Zweck
GET/POST /lists Listen; anlegen (title, icon, listType)
GET/DELETE /lists/{id} Abruf mit Einträgen; Löschen
GET/POST/DELETE /lists/{id}/shares[/{shareId}] Freigaben (targetType, targetId, role: editor/viewer)
POST /lists/{id}/items Eintrag (content, category, quantity)
PATCH /lists/{id}/items/{itemId} Abhaken (isCompleted)
PUT /lists/{id}/items/{itemId} Ändern (content, category, quantity)
DELETE /lists/{id}/items/{itemId} Löschen
POST/PUT /lists/{id}/items/reorder Reihenfolge/Kategorie (items[{id, sortOrder, category, content}])
POST /lists/{id}/clear-completed Erledigte entfernen

Gruppen

Methode Pfad Zweck
GET/POST /teams Eigene Gruppen; anlegen (name, description) – Ersteller wird Gruppen-Admin
PUT/DELETE /teams/{id} Nur Gruppen-Admin
POST /teams/{id}/members Mitglied hinzufügen (userId oder email, role)
PUT/DELETE /teams/{id}/members/{userId} Rolle ändern (admin/member); entfernen
GET/POST/DELETE /organizations, /organizations/{id}[/teams] Veraltet, ungeschützt (FLAW-24)

Administration (role = admin)

Methode Pfad Zweck
GET/POST /admin/users Benutzer auflisten, anlegen (email, password, displayName, role)
PATCH/DELETE /admin/users/{id} displayName, email, role, isActive, discordWebhookUrl; löschen
PUT /admin/users/{id}/password Passwort zurücksetzen
GET/POST/DELETE /admin/invites[/{id}] Einladungen (email, role, teamId, validDays)
GET/PUT /admin/settings instanceName, allowRegistration, sharingMode, SMTP-Felder
POST /admin/smtp/test Testmail (toEmail)

Beispiele

# Gedanken per API-Key erfassen
curl -X POST https://mindsift.example.com/api/v1/webhooks/ingest \
  -H "X-API-Key: mindsift_sec_…" -H "Content-Type: application/json" \
  -d '{"title":"Milch kaufen #einkauf","priority":"high","dueDate":"2026-11-01"}'

# Aufgabenliste nur lesend freigeben
curl -X POST https://mindsift.example.com/api/v1/task-lists/tkl_…/shares \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"targetType":"user","targetId":"usr_…","permission":"viewer"}'