Zum Inhalt springen

REST-API

Klokk bietet eine schreibgeschützte öffentliche REST-API unter /api/v1/* (/status, /users, /clock/states, /time/entries, /time/leaves, /companies). Anfragen werden mit einem API-Schlüssel authentifiziert und pro Scope autorisiert (z. B. read:users, read:time_entries) und auf 60 Anfragen pro Minute und IP begrenzt.und je Schlüssel bzw. persönlicher Verknüpfung begrenzt (RATE_API_PER_MINUTE). Lesen ist der Normalfall; Schreiben für Personen wird gesondert eingeschaltet (unten).

Genehmigte Abwesenheiten – Urlaub, Krankheit, Homeoffice und alle anderen Arten – liefert GET /api/v1/time/leaves?from=JJJJ-MM-TT&to=JJJJ-MM-TT (beide Angaben nötig, höchstens 366 Tage) mit dem Scope read:leave_entries: je Abwesenheit Person, Firma, Art, Zeitraum, Tage und Kommentar.

Erweiterungen können Personen ein- und ausstempeln, Pausen erfassen sowie Abwesenheiten beantragen, ändern und stornieren – nach denselben Regeln wie in Klokk (Monatsabschluss, letzter Arbeitstag, Freigabe). Ab Werk ist alles ausgeschaltet. Super-Admins schalten es unter API & Erweiterungen → Zugriff für Personen ein: Erweiterungen dürfen stempeln und Abwesenheiten verwalten und Persönliche Verknüpfungen. Beim Ausschalten enden alle persönlichen Verknüpfungen, und die Schreibrechte werden aus allen Schlüsseln entfernt.

Eine Erweiterung handelt auf eine von zwei Arten für Personen, festgelegt je Erweiterung:

  • Persönliche Verknüpfung – eine Person verknüpft die App (etwa die Firmen-App) auf einer Zustimmungsseite mit ihrem eigenen Konto. Die App handelt dann nur für diese Person und nur mit den Rechten, denen die Person zugestimmt hat und die der Schlüssel der Erweiterung noch hält: read:time_entries, read:leave_entries, read:clock_states, write:clock, write:absences.
  • Für alle Personen der Firma handeln – der Schlüssel einer an eine Firma gebundenen Erweiterung schreibt für jede Person dieser Firma, benannt über user_id. Gedacht für vertrauenswürdige zentrale Systeme. Mit Abwesenheiten gelten als genehmigt ist die Erweiterung das führende System: Was sie anlegt, ist genehmigt, und sie darf genehmigte Abwesenheiten ändern und stornieren.
Endpunkt Scope Beschreibung
POST /api/v1/clock/in, /clock/out, /clock/break/start, /clock/break/end write:clock Body {"user_id": 7} mit Firmen-Schlüssel, leer mit persönlicher Verknüpfung. Immer zur Serverzeit.
POST /api/v1/absences write:absences type, start_date, end_date, optional half_day (morning/afternoon), comment, external_id. Ein Antrag folgt den Freigaberegeln der Person.
PATCH / DELETE /api/v1/absences/{id} write:absences Nur Abwesenheiten, die die Erweiterung angelegt hat. Ein wartender Antrag wird geändert oder zurückgezogen; für eine genehmigte Abwesenheit beantragt DELETE die Stornierung (202).
GET /api/v1/me – Die Person, für die eine persönliche Verknüpfung handelt, mit den Abwesenheitsarten ihrer Firma (absence_types).
GET /api/v1/time/leaves?updated_since=… read:leave_entries Seitdem angelegte oder geänderte Abwesenheiten in jedem Status; limit/cursor blättern, next_updated_since ist der Wert für den nächsten Abgleich.
GET /api/v1/time/leaves/removed?since=… read:leave_entries Seitdem gelöschte Abwesenheiten – auch nach dem Löschen der Daten einer Person (90 Tage vorgehalten).

external_id ist die eigene ID der Erweiterung für eine Abwesenheit: Mit denselben Daten erneut gesendet, entsteht nichts doppelt (200); mit anderen Daten lautet die Antwort 409 mit der vorhandenen id. Fehler enthalten error (Text) und code (für Programme, z. B. feature_disabled, month_closed, already_clocked_in, token_expired). GET /api/v1/status nennt die Version und die Funktionen, die diese Installation bietet.

Eine App verknüpfen (OAuth 2.0 Authorization Code mit PKCE, nur S256):

  1. Der Super-Admin hakt Verknüpfung durch Personen erlauben an, trägt die Rücksprungadressen ein (exakter Vergleich; https, http nur für localhost, oder ein App-Schema wie com.example.app:/callback) und wählt die Laufzeit (30–365 Tage). Die Seite zeigt die Client-ID.
  2. Die App schickt die Person zu /oauth/authorize?response_type=code&client_id=…&redirect_uri=…&code_challenge=…&code_challenge_method=S256&state=… (optional scope). Die Person meldet sich an, mit zweitem Faktor, und stimmt zu.
  3. Klokk kehrt mit code (eine Minute gültig, einmalig) und state zur Rücksprungadresse zurück.
  4. Der Server der App sendet an /oauth/token (HTTP Basic: Client-ID und Schlüssel der Erweiterung) grant_type=authorization_code, code, redirect_uri und code_verifier und erhält ein Zugriffstoken (eine Stunde) und ein Refresh-Token.
  5. grant_type=refresh_token stellt neue Tokens aus. Ein Refresh-Token gilt einmal; ein bereits benutztes erneut vorzulegen, beendet die Verknüpfung.
  6. Die App beendet eine Verknüpfung mit /oauth/revoke, die Person unter Profil → Verknüpfte Apps. Nach Ablauf der Laufzeit stimmt die Person erneut zu.

Jeder Schreibzugriff steht mit der Erweiterung im Audit-Log, und die Person sieht in ihrer Zeitübersicht, welche Einträge eine App erfasst hat. Die API vom Server der App aufrufen, nicht aus dem Browser: Tokens gehören nicht in Webseiten (CORS erlaubt nur GET). Anfragen sind je Schlüssel bzw. Verknüpfung begrenzt (RATE_API_PER_MINUTE), sodass ein Firmen-Server für viele Personen stempeln kann; fehlgeschlagene Anmeldungen sind auf 30 pro Minute und Adresse begrenzt.

Super-Admins verwalten Integrationen unter API & Erweiterungen (/admin/extensions). Jede Integration bündelt einen API-Schlüssel, seine Scopes und einen Verbindungsmodus:

  • Nur API — die Erweiterung ruft die obige REST-API mit ihrem Schlüssel auf.
  • Webhooks — Klokk sendet bei Ein-/Ausstempeln und Abwesenheitsereignissen ausgehende HTTP-POSTs.
  • WebSocket — die Erweiterung öffnet eine dauerhafte eingehende Verbindung unter GET /api/v1/extension/connect.

Mit EXTENSIONS_ENABLED=false wird das Erweiterungs-Subsystem auf Netzwerkebene abgeschaltet. Die oben aufgeführten schreibgeschützten REST-API-Endpunkte bleiben verfügbar; nur die Webhook-/WebSocket-Funktionen unten werden deaktiviert. Schreiben für Personen und persönliche Verknüpfungen stehen dann ebenfalls nicht zur Verfügung.

Variable Standard Beschreibung
EXTENSIONS_ENABLED true Aktiviert das Erweiterungs-API-Subsystem. Bei false: /admin/extensions und alle Unterrouten liefern 404 Der WebSocket-Endpunkt /api/v1/extension/connect wird nicht registriert Der Versand ausgehender Webhooks entfällt vollständig Es werden keine ExtensionHub-Goroutinen gestartet
WEBHOOK_ALLOW_PRIVATE_TARGETS false SSRF-Schutz für ausgehende Webhooks. Standardmäßig werden Webhook-URLs abgelehnt, die auf Loopback-, private oder Link-Local-Adressen auflösen (auch über Redirects und DNS-Rebinding). Nur auf true setzen, wenn Webhooks bewusst an einen Endpunkt im internen Netz zugestellt werden sollen.