InvoFlux External Punch API Documentation
Version: 2.1
Datum: 08. Juli 2026
Übersicht
Die InvoFlux External Punch API ermöglicht externen Systemen den Zugriff auf die Zeiterfassungsfunktionen von InvoFlux. Alle Endpoints sind token-basiert abgesichert und verwenden REST-Prinzipien mit JSON als Datenformat.
Seit Version 2.0 gibt es zusätzlich zur klassischen Zeiterfassung (Endpoints 1–4) einen Reservierungs-Mechanismus (Endpoints 5–7) für Systeme wie Terminbuchungs-Tools, die einen Mitarbeiter für einen zukünftigen Zeitraum als "verplant" markieren wollen, ohne direkt echte Arbeitszeit zu buchen. Siehe Reservierungen für die Details.
Seit Version 2.1 gibt es zusätzlich einen Abwesenheits-Endpunkt (Endpoint 8), mit dem Terminbuchungs-Systeme mehrtägig im Voraus prüfen können, an welchen Tagen ein Mitarbeiter wegen Urlaub, Zeitausgleich o.ä. nicht verfügbar ist — ohne den konkreten Grund zu erfahren. Siehe Abwesenheiten für die Details.
Basis-Informationen
- Base URL:
https://<deine-invoflux-domain> - Authentifizierung: Header-basierter API-Token
- Content-Type:
application/json(für POST-Requests) - Zeichensatz: UTF-8
Wichtig für Integrationen: Die Base URL ist pro InvoFlux-Installation unterschiedlich (jeder Kunde hat seine eigene Domain). Ein externes System, das mehrere InvoFlux-Kunden anbindet, muss die Base URL pro Kunde/Verbindung konfigurierbar halten — sie darf nicht hartkodiert werden.
Authentifizierung
Alle API-Requests erfordern einen gültigen API-Token im HTTP-Header:
X-API-TOKEN: <ihr-api-token>
Der Token ist pro Benutzer vergeben (nicht pro Firma/Installation) — jeder Mitarbeiter, dessen Daten über die API gelesen oder geschrieben werden sollen, braucht grundsätzlich seinen eigenen Token, sofern die aufrufende Aktion sich auf "den aktuell authentifizierten Benutzer" bezieht (Endpoints 1–3). Bei Endpoints, die einen Ziel-Benutzer per UUID adressieren (Endpoints 4–7), kann ein Admin/TimeAdmin-Token verwendet werden, das für alle Mitarbeiter gilt.
Token generieren
- Als Benutzer mit
ROLE_MANAGERoderROLE_ADMINin InvoFlux einloggen - Profil aufrufen (
/profile/edit) - Im Abschnitt "API-Zugriff" den Button "API-Token erzeugen" klicken
- Token kopieren und sicher aufbewahren
Fehlerhafte Authentifizierung
Bei fehlendem oder ungültigem Token:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "Missing X-API-TOKEN header"
}
oder
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "Invalid API token"
}
workStatus-Enum
Der Arbeitsmodus (workStatus) eines Mitarbeiters kann genau einer der folgenden Werte sein:
| Wert | Bedeutung |
|---|---|
OFFICE | Im Büro (Default) |
AT_CUSTOMER | Beim Kunden |
IN_PROJECT | Im Projekt |
IN_MEETING | Im Meeting |
BUSINESS_TRIP | Dienstreise |
Korrektur ggü. Version 1.0:
HOME_OFFICEexistiert nicht alsworkStatus-Wert und wurde aus dieser Dokumentation entfernt. Ein Request mit einem unbekanntenworkStatus-Wert wird von der API stillschweigend aufOFFICEzurückgesetzt (kein Fehler).
Urlaub und Krankheit sind kein workStatus — sie werden über ein separates Abwesenheits-System verwaltet und tauchen im /status-Endpoint als eigenes Feld absence auf (siehe unten), nicht als workStatus-Wert.
Endpoints
1. Status abrufen GET
Liefert den aktuellen Arbeitsstatus des authentifizierten Benutzers für den heutigen Tag.
Endpoint: GET /ext-api/punch/status
Request-Header:
X-API-TOKEN: <api-token>
Accept: application/json
Query-Parameter: Keine
Erfolgreiche Antwort (200 OK)
Benutzer arbeitet aktuell (im Büro, verfügbar):
{
"status": "WORKING",
"lastEventType": "WORK_START",
"lastEventTime": "2026-01-29T08:15:00+01:00",
"workStartTime": "2026-01-29T08:00:00+01:00",
"workStatus": "OFFICE",
"absence": null,
"available": true
}
Benutzer arbeitet aktuell, aber im Projekt (nicht kurzfristig verfügbar):
{
"status": "WORKING",
"lastEventType": "WORK_START",
"lastEventTime": "2026-01-29T10:00:00+01:00",
"workStartTime": "2026-01-29T08:00:00+01:00",
"workStatus": "IN_PROJECT",
"absence": null,
"available": false
}
Benutzer in Pause:
{
"status": "ON_BREAK",
"lastEventType": "BREAK_START",
"lastEventTime": "2026-01-29T12:00:00+01:00",
"workStartTime": "2026-01-29T08:00:00+01:00",
"workStatus": "OFFICE",
"absence": null,
"available": false
}
Benutzer hat heute noch nicht gearbeitet:
{
"status": "NOT_STARTED",
"lastEventType": null,
"lastEventTime": null,
"workStartTime": null,
"workStatus": null,
"absence": null,
"available": false
}
Benutzer hat Arbeit beendet:
{
"status": "FINISHED",
"lastEventType": "WORK_END",
"lastEventTime": "2026-01-29T16:30:00+01:00",
"workStartTime": null,
"workStatus": null,
"absence": null,
"available": false
}
Benutzer hat heute genehmigten Urlaub/ist krankgemeldet (unabhängig vom Stempel-Status):
{
"status": "NOT_STARTED",
"lastEventType": null,
"lastEventTime": null,
"workStartTime": null,
"workStatus": null,
"absence": "VACATION",
"available": false
}
Status-Werte
| Wert | Bedeutung |
|---|---|
NOT_STARTED | Heute noch keine Arbeit erfasst |
WORKING | Aktuell am Arbeiten |
ON_BREAK | Aktuell in Pause |
FINISHED | Arbeit für heute beendet |
Response-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
status | string | Siehe Tabelle oben |
lastEventType | string|null | Typ des letzten Zeiterfassungs-Events (WORK_START, WORK_END, BREAK_START, BREAK_END) |
lastEventTime | string|null | Zeitpunkt des letzten Events (ISO 8601) |
workStartTime | string|null | Zeitpunkt des ersten WORK_START am heutigen Tag, falls aktuell WORKING/ON_BREAK |
workStatus | string|null | Aktueller Arbeitsmodus, siehe workStatus-Enum. null, wenn heute noch keine Arbeit erfasst oder bereits beendet |
absence | string|null | Typ einer genehmigten Abwesenheit am heutigen Tag (z.B. VACATION, SICK, HOLIDAY), sonst null |
available | boolean | Konsolidiertes Verfügbarkeits-Flag für Kurzfrist-Buchungen: true nur wenn status = WORKING und workStatus = OFFICE und absence = null |
availablewurde speziell für Systeme eingeführt, die kurzfristig entscheiden müssen, ob ein Mitarbeiter spontan ansprechbar ist (z.B. Terminbuchungs-Tools). Es fasst alle relevanten Bedingungen in einem einzigen Boolean zusammen, damit Integrationen nicht selbststatus/workStatus/absencekombinieren müssen.
Beispiel-Request (cURL)
curl -X GET https://ihre-domain.invoflux.de/ext-api/punch/status \
-H "X-API-TOKEN: abc123def456..." \
-H "Accept: application/json"
1b. Status eines Mitarbeiters per UUID abrufen GET
Gleiche Response wie oben, aber für einen beliebigen Mitarbeiter (per externalUuid), aufrufbar mit einem Admin/TimeAdmin-Token.
Endpoint: GET /ext-api/punch/status/{uuid}
Erfolgreiche Antwort (200 OK): Wie bei Endpoint 1, zusätzlich mit Feld user (die angefragte UUID).
2. Arbeit starten POST
Startet eine Arbeitszeit für den authentifizierten Benutzer.
Endpoint: POST /ext-api/punch/work-start
Request-Header:
X-API-TOKEN: <api-token>
Content-Type: application/json
Accept: application/json
Request-Body (JSON, optional):
{
"workStatus": "OFFICE",
"projectId": 123
}
Body-Parameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
workStatus | string | Nein | Arbeitsmodus (Default: OFFICE). Siehe workStatus-Enum |
projectId | integer | Nein | ID eines aktiven Projekts. Nur bei workStatus: IN_PROJECT sinnvoll |
Erfolgreiche Antwort (200 OK)
Mit Projekt:
{
"success": true,
"type": "WORK_START",
"occurredAt": "2026-01-29T08:00:00+01:00",
"workStatus": "IN_PROJECT",
"project": {
"id": 123,
"name": "Website-Relaunch"
}
}
Ohne Projekt:
{
"success": true,
"type": "WORK_START",
"occurredAt": "2026-01-29T08:00:00+01:00",
"workStatus": "OFFICE",
"project": null
}
Fehlerfälle
Projekt nicht gefunden (404 Not Found):
{
"error": "Project not found"
}
Beispiel-Request (cURL)
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/work-start \
-H "X-API-TOKEN: abc123def456..." \
-H "Content-Type: application/json" \
-d '{
"workStatus": "OFFICE",
"projectId": 123
}'
3. Arbeit beenden POST
Beendet eine laufende Arbeitszeit für den authentifizierten Benutzer.
Endpoint: POST /ext-api/punch/work-end
Request-Header:
X-API-TOKEN: <api-token>
Accept: application/json
Request-Body: Leer (kein Body erforderlich)
Erfolgreiche Antwort (200 OK)
{
"success": true,
"type": "WORK_END",
"occurredAt": "2026-01-29T16:30:00+01:00"
}
Beispiel-Request (cURL)
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/work-end \
-H "X-API-TOKEN: abc123def456..." \
-H "Accept: application/json"
4. Manuelle Tagesbuchung erstellen POST
Erstellt eine vollständige Tagesbuchung für einen beliebigen Benutzer (per UUID). Dieser Endpoint ist für externe Systeme gedacht, die nachträglich (rückwirkend) Zeiten importieren möchten — nicht für zukünftige Termine/Reservierungen. Für zukünftige Zeiträume siehe Reservierungen.
Endpoint: POST /ext-api/punch/entry
Request-Header:
X-API-TOKEN: <api-token>
Content-Type: application/json
Accept: application/json
Request-Body (JSON):
{
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"date": "2026-01-28",
"start": "08:00",
"end": "16:30",
"breakMinutes": 30,
"projectId": 123,
"workStatus": "OFFICE",
"reason": "Import aus externem System"
}
Body-Parameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
user | string | Ja | UUID des Benutzers (Feld externalUuid in der User-Tabelle) |
date | string | Ja | Datum im Format Y-m-d (z.B. 2026-01-28) |
start | string | Ja | Startzeit im Format HH:mm (z.B. 08:00) |
end | string | Ja | Endzeit im Format HH:mm (z.B. 16:30) |
breakMinutes | integer | Nein | Pausenzeit in Minuten (Default: 0) |
projectId | integer | Nein | ID eines aktiven Projekts |
workStatus | string | Nein | Arbeitsmodus (Default: OFFICE) |
reason | string | Ja | Begründung für die manuelle Buchung (darf nicht leer sein) |
Achtung: Dieser Endpoint erzeugt echte
WORK_START/WORK_END-Events, die in die Tagesberechnung (plannedMinutes/netMinutes/overtimeMinutes) einfließen. Wird für denselben Tag später zusätzlich real gestempelt, werden beide Zeiträume addiert (InvoFlux erlaubt bewusst beliebig viele Stempel-Paare pro Tag, z.B. für private Unterbrechungen). Für reine "wird dieser Mitarbeiter zu diesem Zeitpunkt verplant, ohne dass real gearbeitete Zeit doppelt gezählt wird"-Anwendungsfälle den Reservierungs-Endpoint verwenden, nicht diesen.
Restriktionen
Für Benutzer ohne ROLE_TIMEADMIN / ROLE_ADMIN:
- Nur vergangene Tage: Das Datum muss in der Vergangenheit liegen
- Maximal 7 Tage zurück: Das Datum darf nicht älter als 7 Tage sein
- Keine bestehenden Buchungen: Für den Tag dürfen noch keine Zeitbuchungen existieren
Für Benutzer mit ROLE_TIMEADMIN / ROLE_ADMIN:
Keine Einschränkungen bei Datum/Vorbuchungen – auch zukünftige Daten werden angenommen (siehe Warnhinweis oben zur Doppelzählung).
Erfolgreiche Antwort (200 OK)
{
"success": true,
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"date": "2026-01-28",
"plannedMinutes": 480,
"netMinutes": 450,
"overtimeMinutes": -30
}
Fehlerfälle
Fehlende Pflichtfelder (400 Bad Request):
{
"error": "missing_fields",
"message": "Fields \"user\", \"date\", \"start\", \"end\" are required."
}
Ungültiges Datumsformat (400 Bad Request):
{
"error": "invalid_date",
"message": "Invalid date format, expected Y-m-d."
}
Ungültiges Zeitformat (400 Bad Request):
{
"error": "invalid_time",
"message": "Invalid time format, expected HH:mm."
}
Endzeit vor oder gleich Startzeit (400 Bad Request):
{
"error": "time_range_invalid",
"message": "End time must be after start time."
}
Fehlende Begründung (400 Bad Request):
{
"error": "missing_reason",
"message": "A reason for the manual entry is required."
}
Benutzer nicht gefunden (404 Not Found):
{
"error": "user_not_found",
"message": "User with given UUID not found."
}
Projekt nicht gefunden/inaktiv (404 Not Found):
{
"error": "project_not_found",
"message": "Projekt nicht gefunden oder inaktiv."
}
Tag bereits gebucht – nur für Nicht-Admins (403 Forbidden):
{
"error": "already_booked",
"message": "Für diesen Tag existieren bereits Buchungen. Bitte kontaktiere einen Administrator für Korrekturen."
}
Datum liegt nicht in Vergangenheit – nur für Nicht-Admins (403 Forbidden):
{
"error": "not_past",
"message": "Manuelle Buchungen sind nur für vergangene Tage erlaubt."
}
Datum älter als 7 Tage – nur für Nicht-Admins (403 Forbidden):
{
"error": "too_old",
"message": "Manuelle Buchungen sind nur bis zu 7 Tage rückwirkend möglich."
}
Unerwarteter Server-Fehler (400 Bad Request):
{
"error": "exception",
"message": "Detaillierte Fehlermeldung..."
}
Beispiel-Request (cURL)
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/entry \
-H "X-API-TOKEN: abc123def456..." \
-H "Content-Type: application/json" \
-d '{
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"date": "2026-01-28",
"start": "08:00",
"end": "16:30",
"breakMinutes": 30,
"projectId": 123,
"workStatus": "OFFICE",
"reason": "Import aus externem Zeiterfassungssystem"
}'
Reservierungen
Neu in Version 2.0.
Reservierungen bilden einen komplett anderen Anwendungsfall ab als entry (Endpoint 4): Ein externes Buchungssystem (z.B. ein Terminkalender) will einen Mitarbeiter für einen zukünftigen Zeitraum als "verplant" markieren, ohne dass diese Zeit automatisch als real gearbeitete Zeit in die Tagesberechnung einfließt — schließlich steht zum Buchungszeitpunkt noch nicht fest, ob der Mitarbeiter zum Termin überhaupt im Dienst sein wird.
Funktionsprinzip
- Das externe System legt per
POST /ext-api/reservationseine Reservierung mit StatusPENDINGan. Es wird kein Zeiterfassungs-Event erzeugt. - Ein interner InvoFlux-Cronjob prüft alle 5 Minuten fällige Reservierungen (deren Start erreicht ist) anhand der tatsächlichen Stempel-Historie:
- War der Mitarbeiter zum exakten Reservierungs-Start-Zeitpunkt eingestempelt (offener
WORK_START, keinWORK_ENDdazwischen)? → Reservierung wirdCONFIRMED, und die Projektzeit wird ab diesem Zeitpunkt als Status-Wechsel auf der laufenden Schicht gebucht (workStatus: IN_PROJECT, kein eigenes, zusätzliches Zeitpaar — keine Doppelzählung). - War er nicht eingestempelt? → Reservierung wird
CANCELLED, keine Zeit wird gebucht.
- War der Mitarbeiter zum exakten Reservierungs-Start-Zeitpunkt eingestempelt (offener
- Diese Prüfung ist ein einmaliger, historischer Zeitpunkt-Check exakt zum Reservierungsbeginn. Was der Mitarbeiter danach tut (z.B. normal weiterarbeiten, später auschecken) hat keinen Einfluss mehr auf das Ergebnis.
- Der Rückwechsel vom
IN_PROJECT-Status zurück aufOFFICE(oder einen anderen Status) nach Ende der Reservierung erfolgt nicht automatisch — das macht der Mitarbeiter bewusst selbst über die normale Zeiterfassung, da InvoFlux nicht wissen kann, ob die tatsächliche Projektarbeit exakt zum geplanten Ende endet.
Reservierungs-Status
| Status | Bedeutung |
|---|---|
PENDING | Reservierung angelegt, Start noch nicht erreicht oder noch nicht geprüft |
CONFIRMED | Mitarbeiter war zum Start eingestempelt, Projektzeit wurde gebucht |
CANCELLED | Mitarbeiter war nicht eingestempelt, oder Reservierung wurde extern storniert |
5. Reservierung anlegen POST
Endpoint: POST /ext-api/reservations
Request-Header:
X-API-TOKEN: <api-token>
Content-Type: application/json
Accept: application/json
Request-Body (JSON):
{
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"date": "2026-07-10",
"start": "10:00",
"end": "12:00",
"projectId": 123,
"reason": "VQBooking: Kunde Müller GmbH – Beratungstermin",
"externalRef": "vqbooking-booking-4711"
}
Body-Parameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
user | string | Ja | UUID des Benutzers (externalUuid) |
date | string | Ja | Datum im Format Y-m-d |
start | string | Ja | Startzeit im Format HH:mm |
end | string | Ja | Endzeit im Format HH:mm, muss nach start liegen |
projectId | integer | Nein | ID eines aktiven Projekts. Ohne Angabe wird bei Bestätigung workStatus: IN_PROJECT ohne Projektbezug gebucht |
reason | string | Nein | Freitext, erscheint als Buchungsgrund, falls die Reservierung bestätigt wird |
externalRef | string | Nein | Freie Referenz-ID des aufrufenden Systems (z.B. Buchungs-ID), rein informativ, für eigene Zuordnung |
Erfolgreiche Antwort (201 Created)
{
"success": true,
"id": 42,
"status": "PENDING"
}
id ist die InvoFlux-interne Reservierungs-ID — diese unbedingt speichern, sie wird für Abfrage und Stornierung benötigt.
Fehlerfälle
Analog zu Endpoint 4: missing_fields (400), user_not_found (404), invalid_date/invalid_time (400), time_range_invalid (400), project_not_found (404).
Beispiel-Request (cURL)
curl -X POST https://ihre-domain.invoflux.de/ext-api/reservations \
-H "X-API-TOKEN: abc123def456..." \
-H "Content-Type: application/json" \
-d '{
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"date": "2026-07-10",
"start": "10:00",
"end": "12:00",
"reason": "VQBooking: Kunde Müller GmbH – Beratungstermin",
"externalRef": "vqbooking-booking-4711"
}'
6. Reservierung abrufen GET
Endpoint: GET /ext-api/reservations/{id}
Erfolgreiche Antwort (200 OK)
{
"id": 42,
"status": "CONFIRMED",
"workDate": "2026-07-10",
"startAt": "2026-07-10T10:00:00+02:00",
"endAt": "2026-07-10T12:00:00+02:00",
"checkedAt": "2026-07-10T10:00:12+02:00"
}
checkedAt ist null, solange die Reservierung noch PENDING ist (Start noch nicht erreicht/geprüft).
Fehlerfälle
Nicht gefunden (404 Not Found):
{
"error": "not_found",
"message": "Reservation not found."
}
7. Reservierung stornieren DELETE
Storniert eine noch nicht bestätigte Reservierung, z.B. weil die zugrunde liegende Buchung im externen System storniert oder verschoben wurde.
Endpoint: DELETE /ext-api/reservations/{id}
Erfolgreiche Antwort (200 OK)
{
"success": true,
"id": 42,
"status": "CANCELLED"
}
Ist die Reservierung bereits CANCELLED, ist der Aufruf idempotent (gleiche 200-Antwort, kein Fehler).
Fehlerfälle
Reservierung bereits bestätigt (409 Conflict):
Wenn der Mitarbeiter bereits als anwesend erkannt und die Projektzeit real gebucht wurde, kann die Reservierung nicht mehr einfach zurückgenommen werden — die entsprechende Arbeitszeit ist inzwischen ein echter Zeiterfassungs-Eintrag.
{
"error": "already_confirmed",
"message": "Mitarbeiter war bereits eingebucht, Zeit wurde real gebucht. Storno nur über manuelle Korrektur möglich."
}
In diesem Fall muss die Korrektur der gebuchten Zeit manuell im InvoFlux-Backend durch einen Admin/TimeAdmin erfolgen.
Nicht gefunden (404 Not Found):
{
"error": "not_found",
"message": "Reservation not found."
}
Beispiel-Request (cURL)
curl -X DELETE https://ihre-domain.invoflux.de/ext-api/reservations/42 \
-H "X-API-TOKEN: abc123def456..."
Abwesenheiten
Neu in Version 2.1.
Liefert für einen Mitarbeiter, an welchen Tagen innerhalb eines Zeitraums er nicht verfügbar ist (Urlaub, Krankheit, Berufsschule, Sonstiges, oder Zeitausgleich wegen Überstunden). Gedacht für Terminbuchungs-Systeme, die vor der Buchung mehrtägig im Voraus prüfen wollen, an welchen Tagen ein Mitarbeiter grundsätzlich in Frage kommt — im Unterschied zu /ext-api/punch/status/{uuid} (Endpoint 1b), das nur die aktuelle Kurzfrist-Verfügbarkeit für jetzt liefert.
Datenschutz: Diese API gibt bewusst keinen Grund und keinen Typ der Abwesenheit zurück — nur ob ein Tag verfügbar ist oder nicht. Damit werden keine gesundheitsbezogenen Daten (z.B. Krankmeldungen) an das externe System weitergegeben.
8. Abwesenheiten abfragen GET
Endpoint: GET /ext-api/absences/{uuid}?from=YYYY-MM-DD&to=YYYY-MM-DD
Request-Header:
X-API-TOKEN: <api-token>
Accept: application/json
Query-Parameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
from | string | Ja | Beginn des Abfragezeitraums, Format Y-m-d |
to | string | Ja | Ende des Abfragezeitraums, Format Y-m-d, muss auf/nach from liegen |
Der Zeitraum darf maximal 366 Tage umfassen.
Erfolgreiche Antwort (200 OK)
{
"user": "8c88c0c0-1234-4abc-9def-0123456789ab",
"from": "2026-08-01",
"to": "2026-08-31",
"unavailable": [
{ "from": "2026-08-10", "to": "2026-08-14" },
{ "from": "2026-08-24", "to": "2026-08-24" }
]
}
Ist der Mitarbeiter im gesamten Zeitraum durchgehend verfügbar, ist unavailable ein leeres Array.
Response-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
user | string | Die angefragte UUID |
from / to | string | Der abgefragte Zeitraum (Bestätigung der Query-Parameter) |
unavailable | array | Liste zusammenhängender Zeiträume (from/to, jeweils Y-m-d), an denen der Mitarbeiter nicht verfügbar ist. Fasst genehmigten Urlaub, genehmigte sonstige Abwesenheiten und Zeitausgleich zusammen, ohne den Grund offenzulegen |
Fehlerfälle
Benutzer nicht gefunden (404 Not Found):
{
"error": "user_not_found",
"message": "User with given UUID not found."
}
Kein Zugriff — Token gehört nicht diesem Mitarbeiter und ist kein Admin/TimeAdmin-Token (403 Forbidden):
{
"error": "forbidden",
"message": "Kein Zugriff auf Abwesenheiten dieses Mitarbeiters."
}
Fehlende Query-Parameter (400 Bad Request):
{
"error": "missing_fields",
"message": "Query-Parameter \"from\" und \"to\" (Y-m-d) sind erforderlich."
}
Ungültiges Datumsformat (400 Bad Request):
{
"error": "invalid_date",
"message": "Invalid date format, expected Y-m-d."
}
Zeitraum ungültig, to vor from (400 Bad Request):
{
"error": "range_invalid",
"message": "\"to\" muss nach \"from\" liegen."
}
Zeitraum zu groß, mehr als 366 Tage (400 Bad Request):
{
"error": "range_too_large",
"message": "Zeitraum darf maximal 366 Tage umfassen."
}
Beispiel-Request (cURL)
curl -X GET "https://ihre-domain.invoflux.de/ext-api/absences/8c88c0c0-1234-4abc-9def-0123456789ab?from=2026-08-01&to=2026-08-31" \
-H "X-API-TOKEN: abc123def456..." \
-H "Accept: application/json"
Fehlerbehandlung
HTTP-Statuscodes
| Code | Bedeutung |
|---|---|
200 OK | Request erfolgreich |
201 Created | Ressource erfolgreich angelegt (z.B. neue Reservierung) |
400 Bad Request | Ungültige Eingabedaten oder fehlende Pflichtfelder |
401 Unauthorized | Fehlende oder ungültige Authentifizierung |
403 Forbidden | Keine Berechtigung für diese Aktion |
404 Not Found | Ressource (User, Projekt, Reservierung) nicht gefunden |
409 Conflict | Aktion nicht möglich, da die Ressource sich bereits in einem finalen Zustand befindet (z.B. Storno einer bereits bestätigten Reservierung) |
Fehlerformat
Alle Fehlermeldungen folgen diesem Format:
{
"error": "error_code",
"message": "Menschenlesbare Fehlerbeschreibung"
}
Benutzer-UUID (externalUuid)
Für die externe API wird empfohlen, Benutzer über eine UUID zu identifizieren statt über interne Datenbank-IDs.
UUID in der Datenbank anlegen
SQL-Migration:
ALTER TABLE user
ADD COLUMN external_uuid VARCHAR(36) DEFAULT NULL,
ADD UNIQUE INDEX UNIQ_USER_EXTERNAL_UUID (external_uuid);
UUID für Benutzer generieren
Beim Erstellen/Bearbeiten eines Benutzers:
use Symfony\Component\Uid\Uuid;
if (!$user->getExternalUuid()) {
$user->setExternalUuid(Uuid::v4()->toRfc4122());
}
Die UUID kann dann in externen Systemen gespeichert und für API-Requests verwendet werden.
Sicherheitshinweise
- API-Token sicher aufbewahren: Tokens niemals in Versionskontrolle committen oder öffentlich zugänglich machen
- HTTPS verwenden: Alle API-Requests sollten über HTTPS erfolgen
- Token-Rotation: Regelmäßig neue Tokens generieren und alte widerrufen
- Minimale Berechtigungen: Nur Benutzern mit
ROLE_MANAGERoderROLE_ADMINAPI-Token gewähren - Rate Limiting: Bei massenhaftem Import externe Rate Limits beachten
- Base URL nicht hartkodieren: Jede InvoFlux-Installation hat eine eigene Domain — bei Integrationen, die mehrere Kunden bedienen, muss die Base URL Teil der Verbindungs-Konfiguration sein, nicht des Programmcodes
Beispiel-Workflow: Externes Zeiterfassungssystem
Szenario
Ein externes Terminal-System soll Arbeitszeiten an InvoFlux übermitteln.
Implementierung
1. Setup:
- Manager-Benutzer in InvoFlux anlegen
- API-Token im Profil generieren
- Token im externen System hinterlegen
2. Täglicher Arbeitsbeginn:
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/work-start \
-H "X-API-TOKEN: abc123..." \
-d '{"workStatus":"OFFICE"}'
3. Status während des Tages abfragen:
curl -X GET https://ihre-domain.invoflux.de/ext-api/punch/status \
-H "X-API-TOKEN: abc123..."
4. Arbeitsende:
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/work-end \
-H "X-API-TOKEN: abc123..."
5. Nachträglicher Import (z.B. für vergessene Buchungen):
curl -X POST https://ihre-domain.invoflux.de/ext-api/punch/entry \
-H "X-API-TOKEN: abc123..." \
-H "Content-Type: application/json" \
-d '{
"user": "8c88c0c0-...",
"date": "2026-01-27",
"start": "09:00",
"end": "17:00",
"breakMinutes": 45,
"reason": "Nachträglicher Import vom Terminal"
}'
Beispiel-Workflow: Terminbuchungs-System (z.B. VQBooking)
Szenario
Ein Terminbuchungs-System soll Mitarbeiter für bestätigte Termine reservieren und kurzfristige Verfügbarkeit prüfen.
Implementierung
1. Setup pro Mitarbeiter/Kalenderverbindung:
- Für jeden Mitarbeiter, der über das Buchungssystem verplant werden soll, wird in InvoFlux dessen
externalUuidbenötigt sowie ein API-Token (kann ein gemeinsamer Admin/TimeAdmin-Token für alle Reservierungs-/Statusaufrufe sein, siehe Hinweis zu Endpoints 4–7) - Base URL der InvoFlux-Instanz im Buchungssystem hinterlegen (pro Kunde konfigurierbar, siehe Sicherheitshinweise)
2. Buchung bestätigt → Reservierung anlegen:
curl -X POST https://ihre-domain.invoflux.de/ext-api/reservations \
-H "X-API-TOKEN: abc123..." \
-H "Content-Type: application/json" \
-d '{
"user": "8c88c0c0-...",
"date": "2026-07-10",
"start": "10:00",
"end": "12:00",
"reason": "VQBooking: Kunde Müller GmbH – Beratungstermin",
"externalRef": "vqbooking-booking-4711"
}'
→ Reservierungs-id aus der Antwort speichern (mit der Buchung verknüpfen).
3. Buchung storniert/verschoben → Reservierung stornieren:
curl -X DELETE https://ihre-domain.invoflux.de/ext-api/reservations/42 \
-H "X-API-TOKEN: abc123..."
Falls 409 already_confirmed zurückkommt: Der Mitarbeiter war zum Termin bereits als anwesend erkannt und die Zeit real gebucht — hier ist keine automatische Rücknahme mehr möglich.
4. Kurzfrist-Slot angefragt (z.B. minAdvanceHours = 0) → Verfügbarkeit live prüfen:
curl -X GET https://ihre-domain.invoflux.de/ext-api/punch/status/8c88c0c0-... \
-H "X-API-TOKEN: abc123..."
→ Slot nur anzeigen, wenn available: true in der Antwort.
5. Terminkalender für die nächsten Wochen anzeigen → mehrtägig prüfen, an welchen Tagen der Mitarbeiter grundsätzlich ausfällt:
curl -X GET "https://ihre-domain.invoflux.de/ext-api/absences/8c88c0c0-...?from=2026-07-08&to=2026-08-08" \
-H "X-API-TOKEN: abc123..."
→ Tage, die in unavailable auftauchen, im Kalender des Buchungssystems von vornherein nicht als buchbar anzeigen (ohne den Grund zu übernehmen/anzuzeigen).
Support
Bei Fragen zur API-Integration oder technischen Problemen:
- Dokumentation: Diese Datei
- Technischer Support: support@invoflux.de
- Version: 2.1 (Stand: 08.07.2026)
Changelog
Version 2.1 (08.07.2026)
- Neuer Endpoint:
GET /ext-api/absences/{uuid}— liefert für einen Zeitraum, an welchen Tagen ein Mitarbeiter wegen Urlaub, sonstiger genehmigter Abwesenheit oder Zeitausgleich (Überstunden-Freizeit) nicht verfügbar ist (siehe Abwesenheiten) - Bewusste Datenschutz-Entscheidung: Der Endpoint gibt nur eine neutrale Verfügbarkeits-Information zurück, keinen Abwesenheitsgrund/-typ — insbesondere werden keine Krankheitsdaten an externe Systeme weitergegeben
Version 2.0 (03.07.2026)
- Neue Endpoints:
POST /ext-api/reservations,GET /ext-api/reservations/{id},DELETE /ext-api/reservations/{id}— Reservierungsmechanismus für Terminbuchungs-Integrationen (siehe Reservierungen) GET /ext-api/punch/statusund/status/{uuid}liefern zusätzlichworkStatus,absenceund ein konsolidiertesavailable-Flag- Korrektur:
HOME_OFFICEalsworkStatus-Wert entfernt (existierte nie serverseitig), vollständige Enum-Liste ergänzt - HTTP-Statuscodes
201 Createdund409 Conflictergänzt - Hinweis zur Doppelzählungs-Problematik bei
entrymit Zukunftsdaten ergänzt - Hinweis zur konfigurierbaren Base URL bei Mandanten-übergreifenden Integrationen ergänzt
Version 1.0 (29.01.2026)
- Initiale API-Version
- Endpoints: status, work-start, work-end, entry
- Token-basierte Authentifizierung
- Unterstützung für Projekte und Work-Status