Calendar API — Entwickler-Referenz
REST-API fuer das Advanced Calendar Modul. Alle Endpunkte unter
/api/platform/v1/calendar/.
Authentifizierung
Alle Endpunkte erfordern einen Bearer Token im Authorization Header. Sowohl Platform-JWT (Web-Client) als auch Customer-JWT (Portal) werden akzeptiert.
Authorization: Bearer {token}Layer-Endpunkte
GET /calendar/layers
Gibt alle Kalender-Layer zurueck die der Benutzer sehen darf.
Admin/Portal-User: Sehen alle Layer des Tenants. Normale User: Sehen Layer 1 (Schule) + Layer fuer Spaces in denen sie Mitglied sind.
Response:
{
"layers": [
{
"id": "cmngef4yw...",
"tenantId": "cmneba...",
"spaceId": null,
"userId": null,
"level": 1,
"name": "Schulkalender",
"color": "#3b82f6",
"isPublic": false,
"publicToken": null,
"eventCount": 42,
"subscribed": true,
"createdAt": "2026-04-01T..."
}
]
}POST /calendar/layers
Erstellt einen neuen Layer.
Request Body:
{
"spaceId": "Kollegium",
"level": 2,
"name": "Feiertage",
"color": "#ef4444"
}| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
spaceId | string | Nein | Space-ID (null fuer Level 1) |
level | number | Ja | 1=Schule, 2=Space, 3=Raum, 4=Nutzer |
name | string | Ja | Name des Layers (max 255 Zeichen) |
color | string | Nein | Hex-Farbe (Default: #3b82f6) |
Level 1 kann nur von Admins erstellt werden.
PATCH /calendar/layers/:layerId
Aktualisiert einen Layer.
Request Body (alle optional):
{
"name": "Neuer Name",
"color": "#10b981",
"isPublic": true
}Bei isPublic: true wird automatisch ein publicToken generiert.
DELETE /calendar/layers/:layerId
Loescht einen Layer und alle zugehoerigen Events. HTTP 204.
POST /calendar/layers/:layerId/subscribe
Blendet einen Layer fuer den aktuellen Benutzer ein. HTTP 201.
DELETE /calendar/layers/:layerId/subscribe
Blendet einen Layer fuer den aktuellen Benutzer aus. HTTP 204.
Event-Endpunkte
GET /calendar/events
Gibt Events fuer die angegebenen Layer im Zeitraum zurueck.
Query-Parameter:
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
from | ISO 8601 | Ja | Startdatum |
to | ISO 8601 | Ja | Enddatum |
layers | string | Nein | Komma-getrennte Layer-IDs. Default: alle abonnierten Layer |
Response:
{
"events": [
{
"id": "cmnh...",
"layerId": "cmngef...",
"tenantId": "cmneba...",
"uid": "abc123@prilog.chat",
"title": "Lehrerkonferenz",
"description": "Tagesordnung siehe Anhang",
"location": "Aula",
"dtstart": "2026-04-15T14:00:00.000Z",
"dtend": "2026-04-15T16:00:00.000Z",
"allDay": false,
"rrule": null,
"exdates": [],
"status": "CONFIRMED",
"transparency": "OPAQUE",
"color": null,
"categories": [],
"organizerId": "@admin:schule.prilog.team",
"attendees": [],
"version": 1,
"createdAt": "2026-04-01T...",
"updatedAt": "2026-04-01T...",
"layer": {
"color": "#3b82f6",
"name": "Schulkalender",
"level": 1
}
}
]
}POST /calendar/events
Erstellt ein neues Event.
Request Body:
{
"layerId": "cmngef4yw...",
"title": "Elternabend",
"description": "Klasse 8a",
"location": "Raum 201",
"dtstart": "2026-04-20T18:00:00.000Z",
"dtend": "2026-04-20T20:00:00.000Z",
"allDay": false,
"rrule": "FREQ=MONTHLY",
"status": "CONFIRMED",
"color": "#ef4444",
"categories": ["eltern", "klasse8"],
"attendees": ["@mueller:schule.prilog.team"]
}| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
layerId | string | Ja | Ziel-Layer |
title | string | Ja | Titel (max 500 Zeichen) |
dtstart | ISO 8601 | Ja | Startzeit |
dtend | ISO 8601 | Nein | Endzeit |
allDay | boolean | Nein | Ganztaegig (Default: false) |
description | string | Nein | Beschreibung (max 10000 Zeichen) |
location | string | Nein | Ort (max 500 Zeichen) |
rrule | string | Nein | Wiederholungsregel (RFC 5545) |
status | string | Nein | TENTATIVE / CONFIRMED / CANCELLED |
color | string | Nein | Ueberschreibt Layer-Farbe |
categories | string[] | Nein | Tags |
attendees | string[] | Nein | Teilnehmer (Matrix-User-IDs) |
PUT /calendar/events/:eventId
Aktualisiert ein Event. Erfordert das version-Feld fuer Optimistic Locking.
Request Body:
{
"title": "Elternabend (verschoben)",
"dtstart": "2026-04-22T18:00:00.000Z",
"version": 1
}Bei Version-Konflikt: HTTP 409 mit Meldung "Termin wurde in der Zwischenzeit geaendert."
DELETE /calendar/events/:eventId
Loescht ein Event. HTTP 204.
iCal-Endpunkte
GET /calendar/ical/:layerId
Gibt den .ics-Feed eines Layers zurueck (authentifiziert).
Response Headers:
Content-Type: text/calendar; charset=utf-8ETag: "{timestamp}"Cache-Control: max-age=300
Unterstuetzt HTTP 304 Not Modified via If-None-Match Header.
GET /calendar/public/:token
Gibt den oeffentlichen .ics-Feed zurueck (kein Login noetig).
Der token wird automatisch generiert wenn ein Layer auf isPublic: true gesetzt wird.
Response Headers:
Content-Type: text/calendar; charset=utf-8Access-Control-Allow-Origin: *
POST /calendar/import
Importiert eine .ics-Datei in einen Layer.
Request Body:
{
"layerId": "cmngef4yw...",
"icsContent": "BEGIN:VCALENDAR\r\nVERSION:2.0\r\n..."
}Response:
{
"imported": 15,
"skipped": 3,
"total": 18
}Duplikate werden anhand der UID erkannt und uebersprungen.
Aufgaben-Kalender-Sync
Aufgaben aus dem Projekt-Modul werden automatisch mit dem Kalender synchronisiert:
- Aufgabe mit Faelligkeitsdatum → CalendarEvent im "Aufgaben {Space}" Layer
- Event-UID:
task-{itemId}@prilog.chat - Ganztaegig von startDate bis dueDate
- Status "done" → Event wird als
CANCELLEDmarkiert - Datum entfernt → Event wird geloescht
- Sync passiert bei: Item Create, Item Update, Item Move
Layer-Hierarchie
| Level | Bezeichnung | Sichtbarkeit | Erstellt durch |
|---|---|---|---|
| 1 | Schule | Alle im Tenant | System (automatisch) |
| 2 | Space | Space-Mitglieder | Admin oder System |
| 3 | Raum | Space-Mitglieder | Admin (zukuenftig) |
| 4 | Nutzer | Nur der Nutzer selbst | Nutzer (zukuenftig) |
Layer 1 wird automatisch beim Aktivieren des Calendar-Moduls erstellt. Layer 2 wird automatisch bei jeder Space-Erstellung erstellt. "Aufgaben {Space}"-Layer werden vom Projekt-Modul erstellt.