# API-Dokumentation

Die SeminarPlan API ist eine Fastify-basierte REST-API mit zwei Generationen von Endpunkten: V1 und V2.

# Übersicht

Die API stellt zwei parallele Endpunkt-Familien bereit:

API-Architektur

V1 V2
Basis-Pfad /v1/{entity} bzw. /api/{entity} /api/v2/{entity}
Architektur Mongoose Model + AbstractController Factory-Routen + LookupService
Daten Roh-Dokumente aus MongoDB Denormalisiert, paginiert, optimiert
Verwendung V1-Frontend, Webseite (CMS-Plugins), Externe V2-Frontend (Desktop-Shell)

Beide Versionen sind gleichzeitig aktiv. V2-Endpunkte sind für das moderne Frontend optimiert und liefern fertig aufbereitete Daten.

# Authentifizierung

Die API verwendet JSON Web Tokens (JWT) zur Authentifizierung.

# Login

POST /v1/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "..."
}

Antwort:

{
  "token": "eyJhbG...",
  "user": { "_id": "...", "name": "...", "group": "user" }
}

# Token verwenden

Das Token wird bei jedem Request als Header mitgeschickt:

token: eyJhbG...

# Öffentliche Routen

Folgende Routen benötigen kein Token:

Route Zweck
POST /v1/login Login
POST /v1/register/* Registrierung
GET /v1/public/* Öffentliche Daten (Feedbacks, Organisation)
POST /v1/orders/place Bestellung aufgeben (Website)
POST /v1/inquiries/place Anfrage aufgeben (Website)
GET /v1/ics/* Kalender-Download (ICS)
GET /v1/api-docs/* Swagger-Dokumentation
GET /v2/api-docs/* Swagger-Dokumentation (V2)
GET /v1/coupons/validate/* Gutschein validieren

Swagger UI

Die API-Dokumentation ist auch interaktiv verfügbar:

  • V1: /v1/api-docs
  • V2: /v2/api-docs

Dort kannst du alle Endpunkte durchsuchen, Parameter sehen und direkt testen.

# V1 Endpunkte

V1-Endpunkte folgen dem klassischen CRUD-Muster:

Methode Route Beschreibung
GET /api/{entity} Alle Einträge laden
GET /api/{entity}/:id Einzelnen Eintrag laden
POST /api/{entity} Neuen Eintrag erstellen
PUT /api/{entity}/:id Eintrag aktualisieren
DELETE /api/{entity}/:id Eintrag löschen (Soft Delete)

# V1 Response-Formate

Liste:

{
  "items": [{ "_id": "...", "title": "..." }, ...]
}

Erstellen / Aktualisieren:

{
  "count": 1,
  "item": { "_id": "...", "title": "..." }
}

# Verfügbare V1-Entitäten

Kontakte, Buchungen, Angebote, Bestellungen, Anfragen, Rechnungen, Gutschriften, Seminare, Feste Termine, Standorte, Räume, Kategorien, Hersteller, Tags, E-Mails, Briefe, Aufgaben, Gesprächsnotizen, Feedbacks, Lernpfade, Gutscheine, Kursunterlagen, Portale, Statische Seiten, Menüs, Förderungen, Wartelisten, Kontaktformularnachrichten, Preisgruppen und weitere.

# V2 Endpunkte

V2-Endpunkte werden über zwei Factory-Funktionen erzeugt:

# createV2ResourceRoutes (Vollständiges CRUD)

Für Entitäten mit Schreibzugriff (Kontakte, Buchungen, Angebote, ...):

Methode Route Beschreibung
GET /api/v2/{entity} Paginierte Liste
GET /api/v2/{entity}/:id Detail-Ansicht (deep populate)
POST /api/v2/{entity} Neuen Eintrag erstellen
PATCH /api/v2/{entity}/:id Eintrag aktualisieren (partial)
DELETE /api/v2/{entity}/:id Eintrag löschen
POST /api/v2/{entity}/search Erweiterte Suche
POST /api/v2/{entity}/resolve Eintrag per Kriterium finden

# createV2LookupRoutes (Nur Lesen)

Für denormalisierte Lesezugriffe (z.B. Feste Termine, Kalender):

Methode Route Beschreibung
GET /api/v2/{entity} Paginierte Liste
GET /api/v2/{entity}/:id Detail-Ansicht

# V2 Response-Formate

Liste:

{
  "items": [{ "_id": "...", "title": "..." }],
  "meta": {
    "total": 142,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}

Detail:

{
  "item": { "_id": "...", "title": "...", "customer": { "name": "..." } }
}

Mutation (Create/Update):

{
  "count": 1,
  "item": { "_id": "...", "title": "..." }
}

Resolve:

{
  "found": true,
  "item": { "_id": "...", "title": "..." }
}

# Standard-Query-Parameter (V2)

Parameter Typ Beschreibung
q string Freitextsuche
limit integer Max. Ergebnisse (Standard: 20, Max: 100)
offset integer Offset für Pagination
statuses string/array Nach Status filtern
sortBy string Sortierfeld
sortType asc / desc Sortierrichtung
ids string/array Bestimmte IDs laden
employeeId string Nach Mitarbeiter filtern
relationKey / relationValue string Nach Beziehung filtern
group string Nach Gruppe filtern
tag string Nach Tag filtern
countOnly boolean Nur Anzahl zurückgeben

# Erweiterte Filter (V2)

V2 unterstützt serialisierte Filter als JSON-Array im Query-Parameter filters:

[
  { "field": "title", "operator": "contains", "value": "Excel" },
  { "field": "createdAt", "operator": "greaterThan", "value": "2025-01-01" }
]

Verfügbare Operatoren:

Operator Beschreibung
contains Enthält (Regex)
containsNot Enthält nicht
isEmpty Feld ist leer
startsWith Beginnt mit
endsWith Endet mit
equals Exakte Übereinstimmung
notEquals Nicht gleich
greaterThan Größer als
lessThan Kleiner als
greaterThanOrEqual Größer oder gleich
lessThanOrEqual Kleiner oder gleich

# V2 Spezial-Endpunkte

Neben den Standard-CRUD-Routen gibt es spezielle Endpunkte:

Endpunkt Beschreibung
GET /api/v2/fixed-dates/schedule Denormalisierte Terminplanung (Kalender, Wochenplan, Raumbelegung)
GET /api/v2/bootstrap Bootstrap-Daten (User, Organisation, ACL) beim Login
GET /api/v2/dashboard/* Dashboard-Statistiken und Widgets
POST /api/v2/search/global Globale Suche über alle Entitäten
GET /api/v2/chat/* Chat-Nachrichten
POST /api/v2/assistant/* KI-Assistent

# LookupService-Pattern

Jede V2-Entität hat einen zugehörigen LookupService (z.B. ContactLookupService, BookingLookupService). Diese Services erben von BaseLookupService und bieten:

Methode Beschreibung
listPage(args) Paginierte Liste mit Suche, Sortierung, Populate
getDetailItem(args) Einzelner Eintrag mit Deep Populate
toListItem(item, stats) Rohdaten → denormalisiertes Listenformat

Jeder LookupService definiert statische Konstanten:

  • *_LIST_SELECT -- Welche Felder in der Liste geladen werden
  • *_LIST_SORT_FIELDS -- Erlaubte Sortierfelder

Beispiel: FixedDateLookupService

Der Schedule-Endpunkt ist ein gutes Beispiel für erweiterte Denormalisierung:

GET /api/v2/fixed-dates/schedule?begin=2026-01-01&end=2026-01-31&statuses=published

Dieser Endpunkt:

  1. Fragt Feste Termine im Datumsbereich ab
  2. Lädt Buchungsstatistiken in einem Batch
  3. Löst Kundennamen auf (für Firmenseminare)
  4. Berechnet Teilnehmerzahlen, Uhrzeiten und Farben
  5. Liefert fertig aufbereitete ScheduleItems zurück

So müssen Kalender, Wochenplan und Raumbelegung keine kompletten Stores laden.

# ACL-System (Berechtigungen)

Die API verwendet ein rollenbasiertes Berechtigungssystem:

Gruppe Beschreibung
guest Nur Lesezugriff auf ausgewählte Bereiche
user Standard-Benutzer mit Lese- und Schreibzugriff
manager Erweiterte Rechte (alle Benutzeraktionen)
admin Vollzugriff inkl. Systemeinstellungen
root Superadmin (nur für Entwickler)

Pro Entität und Gruppe werden Rechte definiert:

Recht Beschreibung
create Neue Einträge erstellen
read Einträge lesen
edit Alle Einträge bearbeiten
editOwn Eigene Einträge bearbeiten
editState Status ändern
delete Einträge löschen

Im Frontend prüfst du Rechte mit:

const { can, isAdmin } = useAcl();
if (can('Booking', 'edit')) { ... }

# WebSocket

Die API stellt eine WebSocket-Verbindung für Echtzeit-Updates bereit:

Event Beschreibung
change Ein Datensatz wurde erstellt, aktualisiert oder gelöscht
lock / unlock Optimistisches Locking (Bearbeitung durch anderen Benutzer)
notification Benachrichtigung an einen Benutzer
task V2-spezifische Aufgabe (z.B. KI-Antwort)

Änderungen werden über das modelToStoreKeys-Mapping in storeHelper.ts an die richtigen Stores weitergeleitet.

# Siehe auch

Last Updated: 4/16/2026, 8:54:41 AM