Zum Hauptinhalt springen

Grundlagen

Beta Die REST-API ist in der Beta. Endpunkte und Felder können sich bis zur Version 1.0.0 noch ändern.

Diese Regeln gelten für alle Endpunkte der TimeMonkey REST-API.

Requests und Antworten​

  • Die API ist rein lesend und nimmt nur GET-Requests an. Andere HTTP-Methoden beantwortet sie mit 405 method_not_allowed und dem Header Allow: GET.
  • Alle Antworten sind JSON, auch Fehler. Die Fehlerform steht unter Fehler und Rate-Limits.
  • Antworten unter /api/v1 tragen den Header X-Request-Id, auch Fehlerantworten wie 404 und 405. Gib diese ID an, wenn du dich wegen eines bestimmten Requests an den Support wendest.
  • Antworten werden nicht zwischengespeichert (Cache-Control: no-store). Jeder Request liefert den aktuellen Stand.
  • Unbekannte Abfrageparameter sind ein Fehler: Die API antwortet dann mit 400 validation_error, statt den Parameter stillschweigend zu ignorieren. Achte deshalb auf die genaue Schreibweise, zum Beispiel employeeId.
  • Unbekannte Pfade unter /api/v1 beantwortet die API mit 404 not_found.

Einzige Ausnahme ist GET /api/v1/openapi.json: Die Spezifikation ist statisch, darf zwischengespeichert werden und hat keine X-Request-Id.

IDs​

Alle IDs sind 24-stellige Hexadezimal-Zeichenketten, zum Beispiel 650a1b2c3d4e5f6071829304. Über sie verknüpfst du die Daten der Endpunkte: Das Feld employeeId eines Stempels entspricht zum Beispiel dem Feld id des Mitarbeiters aus GET /api/v1/employees. Eine ID in falschem Format, etwa als Pfad- oder Filterparameter, führt zu 400 validation_error.

Zeitpunkte​

Zeitpunkte wie Stempelzeiten oder Schichtbeginn liefert die API im Format ISO 8601 in UTC mit Millisekunden, erkennbar am Z am Ende:

"timestamp": "2026-10-01T05:58:12.000Z"

Das entspricht 07:58:12 Uhr deutscher Sommerzeit. Rechne Zeitpunkte für die Anzeige selbst in die Zeitzone Europe/Berlin um, damit Sommer- und Winterzeit richtig berücksichtigt werden.

Datumsangaben und Zeitzone​

TimeMonkey rechnet alle Kalendertage in der Zeitzone Europe/Berlin. Das gilt für Filter und für Datumsfelder in Antworten. Das Feld timeZone von GET /api/v1/company enthält deshalb immer "Europe/Berlin".

  • Datumsfilter wie from und to gibst du im Format YYYY-MM-DD an. Beide Grenzen sind inklusive: from=2026-10-01&to=2026-10-31 umfasst den 1. Oktober ab 00:00 Uhr bis einschließlich 31. Oktober, 24:00 Uhr, jeweils deutscher Zeit.
  • Ungültige Kalenderdaten wie 2026-02-30 und ein to vor from führen zu 400 validation_error.
  • Datumsfelder in Antworten, etwa date der Tagesauswertung oder halfDays bei Abwesenheiten, haben ebenfalls das Format YYYY-MM-DD und beziehen sich auf Kalendertage in Europe/Berlin.

Pro Request ist der Zeitraum begrenzt, damit Abfragen schnell bleiben:

Endpunktfrom und toLängster Zeitraum pro Request
GET /api/v1/stampsPflicht366 Tage
GET /api/v1/shiftsPflicht366 Tage
GET /api/v1/evaluations/daysPflicht92 Tage, to nicht in der Zukunft
GET /api/v1/absencesoptionalkeine Begrenzung

Brauchst du einen längeren Zeitraum, teile ihn auf mehrere Requests auf, zum Beispiel monatsweise.

Dauern​

Alle Dauern liefert die API in Millisekunden als Zahl. Felder mit Dauern enden auf Ms, zum Beispiel workedMs oder weeklyMs.

DauerMillisekunden
1 Minute60000
1 Stunde3600000
8 Stunden28800000
38,5 Stunden138600000

Stunden erhältst du, indem du durch 3.600.000 teilst: 28800000 / 3600000 = 8. Ausnahmen sind annualVacationDays bei Mitarbeitern und das Urlaubskonto vacation der Jahresauswertung: Urlaub wird in Tagen angegeben.

Salden und Summen der Auswertungen können bei Monatsverträgen Nachkommastellen haben, weil TimeMonkey die Monatsstunden auf die Tage verteilt. Runde erst bei der Anzeige, nicht vor dem Weiterrechnen.

Pagination​

Listen-Endpunkte liefern ihre Ergebnisse seitenweise in dieser Form:

Antwort eines Listen-Endpunkts
{
"data": [ ... ],
"nextCursor": "WzE3OTA5MjA4MDAwMDAsIjY3MjBmMGExYjJjM2Q0ZTVmNmE3YjgwMyJd"
}
  • Mit limit legst du fest, wie viele Einträge eine Seite höchstens enthält: 1 bis 500, Standard 100. Die Auswertungs-Endpunkte können eine Seite auch früher beenden, weil ihre Rechenzeit pro Seite begrenzt ist. Eine Seite mit weniger Einträgen ist also nicht automatisch die letzte.
  • Ist nextCursor nicht null, gibt es weitere Einträge. Übergib den Wert beim nächsten Request als Parameter cursor und lass die übrigen Parameter unverändert.
  • Erst wenn nextCursor gleich null ist, hast du die letzte Seite erreicht.
  • Der Cursor ist eine undurchsichtige Zeichenkette: Verwende ihn genau so, wie du ihn bekommen hast, und setze ihn nicht selbst zusammen. Ein veränderter oder ungültiger Cursor führt zu 400 validation_error.

GET /api/v1/areas ist nicht paginiert und liefert nur data. GET /api/v1/company und GET /api/v1/employees/{id} liefern ein einzelnes Objekt.

Die Einträge einer Liste kommen in fester Reihenfolge:

EndpunktSortierung
GET /api/v1/employeesnach id
GET /api/v1/stampsnach timestamp, dann id
GET /api/v1/absencesnach start, dann id
GET /api/v1/shiftsnach start, dann id
GET /api/v1/evaluations/daysnach employeeId, dann date
GET /api/v1/evaluations/monthsnach employeeId, dann month
GET /api/v1/evaluations/yearsnach employeeId

Alle Seiten abrufen​

Jede Seite ist ein eigener Request und zählt für das Rate-Limit. Mit limit=500 brauchst du die wenigsten Requests. Rufe zuerst die erste Seite ab und übergib dann deren nextCursor als cursor für die nächste Seite; lass die übrigen Parameter unverändert. Ersetze im curl-Beispiel <nextCursor> durch den Wert aus der vorherigen Antwort. Sobald nextCursor null ist, hast du alle Seiten.

Terminal
curl -s "https://api.time.monkeymed.de/api/v1/stamps?from=2026-10-01&to=2026-10-31&limit=500" \
-H "Authorization: Bearer $TIMEMONKEY_API_KEY"

curl -s "https://api.time.monkeymed.de/api/v1/stamps?from=2026-10-01&to=2026-10-31&limit=500&cursor=<nextCursor>" \
-H "Authorization: Bearer $TIMEMONKEY_API_KEY"