Zeiterfassung
Die TimeEntry-Entität repräsentiert Zeiteinträge in InLoox. Über die OData-API können Sie Zeiteinträge erstellen, aktualisieren, löschen sowie mit Dokumenten verknüpfen und aus Microsoft-Graph-Kalenderevents erzeugen.
Alle Endpunkte verwenden den Basispfad /odata/TimeEntry. Für die dynamische Listenansicht einschließlich eigener Felder steht /odata/DynamicTimeEntry zur Verfügung.
Zeiteinträge sind stets einem Projekt zugeordnet. Verwenden Sie ProjectId beim Filtern, um nur Zeiteinträge eines bestimmten Projekts abzurufen.
Datenmodell
TimeEntry
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
TimeEntryId | Guid (UUID) | Eindeutiger Bezeichner des Zeiteintrags (Primärschlüssel). |
DisplayName | string? | Anzeigename des Zeiteintrags. |
StartDateTime | DateTimeOffset? | Startdatum und -uhrzeit. |
EndDateTime | DateTimeOffset? | Enddatum und -uhrzeit. |
ProjectId | Guid? | Zugehöriges Projekt. |
DescriptionHTML | string? | Beschreibung als HTML. |
DescriptionText | string? | Beschreibung als Klartext. |
PhaseId | Guid? | Verknüpfte Planungsphase. |
IsBillable | boolean | Gibt an, ob der Zeiteintrag abrechenbar ist. |
PerformedByContactId | Guid | Kontakt-ID der Person, die die Arbeit ausgeführt hat. |
ColorFlag | int32? | Farbmarkierung (als Integer-Wert). |
GroupId | Guid | Gruppen-ID des Zeiteintrags. |
TaskItemId | Guid? | Verknüpfte Aufgabe. |
IsBilled | boolean | Gibt an, ob der Zeiteintrag bereits abgerechnet wurde. |
DurationMinutes | int32 | Dauer in Minuten. |
Endpunkte
CRUD-Operationen
Alle Zeiteinträge aller Projekte abrufen
/odata/TimeEntryUnterstützt OData-Abfrageparameter.
Einen einzelnen Zeiteintrag abrufen
/odata/TimeEntry({key})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Neuen Zeiteintrag erstellen
/odata/TimeEntry| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
Body | Delta<ApiTimeEntry> | ✅ | JSON-Objekt mit den Zeiteintragseigenschaften. |
Wenn PerformedByContactId nicht angegeben wird, wird der Zeiteintrag für den authentifizierten Benutzer erfasst.
Zeiteintrag teilweise aktualisieren
/odata/TimeEntry({key})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | Delta<ApiTimeEntry> | ✅ | JSON-Objekt mit den zu aktualisierenden Feldern. |
Zeiteintrag löschen
/odata/TimeEntry({key})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Das Löschen eines Zeiteintrags ist dauerhaft. Falls der Eintrag bereits abgerechnet wurde, ist das Löschen nicht möglich.
Spezialfunktionen
Kalenderansicht der Zeiteinträge für ein Projekt abrufen
/odata/TimeEntry/GetCalendarTimeEntriesForProject(projectId={projectId},take={take})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
projectId | Guid | ✅ | Die ProjectId. |
take | int32 | ✅ | Maximale Anzahl der zurückgegebenen Einträge. |
Einen Zeiteintrag aus einem Microsoft-Graph-Kalenderevent erstellen
/odata/TimeEntry/CreateTimeEntryFromGraphEvent| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: projectId (Guid, erforderlich) — Das Projekt, in dem der Zeiteintrag erstellt werden soll. graphEventId (string, erforderlich) — Die ID des Microsoft-Graph-Kalenderevents. tagEvent (bool?, optional) — Wenn true, wird dem Kalenderevent die Kategorie "InLoox" hinzugefügt. taskItemId (Guid?, optional) — Optionale Aufgabe, die mit dem Zeiteintrag verknüpft werden soll. |
Mit CreateTimeEntryFromGraphEvent können Sie Outlook-Kalendertermine direkt in Zeiteinträge umwandeln. Dies setzt eine aktive Microsoft-Graph-Integration voraus.
Einen Zeiteintrag kopieren
/odata/TimeEntry({key})/Copy| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId des zu kopierenden Eintrags. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: projectId (Guid?, optional) — Zielprojekt für den kopierten Zeiteintrag. Wenn nicht angegeben, bleibt die Kopie im selben Projekt wie das Original. |
Einen Zeiteintrag mit neuen Datumswerten kopieren
/odata/TimeEntry({key})/CopyWithNewDates| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId des zu kopierenden Eintrags. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: projectId (Guid?, optional) — Zielprojekt für die Kopie. Wenn nicht angegeben, bleibt die Kopie im selben Projekt. startDate (DateTimeOffset?, erforderlich) — Neues Startdatum/-uhrzeit für den kopierten Eintrag (wird als UTC gespeichert). endDate (DateTimeOffset?, erforderlich) — Neues Enddatum/-uhrzeit für den kopierten Eintrag (wird als UTC gespeichert). |
Dokumente
Ein Dokument mit dem Zeiteintrag verknüpfen
/odata/TimeEntry({key})/AddDocumentToTimeEntry| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: documentIds (Guid[], erforderlich) — Array von Dokument-IDs, die mit dem Zeiteintrag verknüpft werden sollen. |
Ein Dokument vom Zeiteintrag entfernen
/odata/TimeEntry({key})/RemoveDocumentFromTimeEntry| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: documentId (Guid, erforderlich) — Die ID des Dokuments, das vom Zeiteintrag entfernt werden soll. |
Verknüpfungen
Eine Verknüpfung zum Zeiteintrag hinzufügen
/odata/TimeEntry({key})/AddRelation| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: itemId (Guid, erforderlich) — Die ID des Elements, das verknüpft werden soll. |
Eine Verknüpfung vom Zeiteintrag entfernen
/odata/TimeEntry({key})/RemoveRelation| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: itemId (Guid, erforderlich) — Die ID des Elements, dessen Verknüpfung entfernt werden soll. |
Kommentare
Alle Zeiteintragskommentare abrufen
/odata/TimeEntryCommentEinen einzelnen Kommentar abrufen
/odata/TimeEntryComment({key})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryCommentId. |
Einen Kommentar zum Zeiteintrag hinzufügen
/odata/TimeEntry({key})/AddNote| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key | Guid | ✅ | Die TimeEntryId. |
Body | object | ✅ | JSON-Objekt mit folgenden Feldern: htmlText (string, erforderlich) — HTML-formatierter Kommentartext. notificationContactIds (Guid[], erforderlich) — Kontakt-IDs, die benachrichtigt werden sollen (kann ein leeres Array [] sein). |
Einen Kommentar vom Zeiteintrag löschen
/odata/TimeEntry/DeleteNote(noteRelationId={noteRelationId})| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
noteRelationId | Guid | ✅ | Die ID der Kommentarverknüpfung. |
Das Löschen eines Kommentars kann nicht rückgängig gemacht werden.
DynamicTimeEntry
Der Endpunkt /odata/DynamicTimeEntry bietet eine schreibgeschützte, abgeflachte Ansicht, die Daten aus Zeiteintrag, Projekt, Planung, Aufgabe und Berechtigungen zusammenführt. Alle Eigenschaften sind mit einem Präfix versehen (z. B. TimeEntry_DisplayName, Project_Name, TaskItem_Name). Eigene Felder folgen dem Muster CF_<Feldname>.
Abgeflachte Zeiteintragsansicht mit Projekt-, Planungs- und Aufgabendaten abrufen
/odata/DynamicTimeEntryDynamicTimeEntry unterstützt ausschließlich GET-Anfragen. Zum Erstellen oder Bearbeiten verwenden Sie die regulären /odata/TimeEntry-Endpunkte.
OData-Abfragebeispiele
Zeiteinträge eines Projekts abrufen
GET /odata/TimeEntry?$filter=ProjectId eq 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Abrechenbare, aber noch nicht abgerechnete Einträge
GET /odata/TimeEntry?$filter=IsBillable eq true and IsBilled eq false
Zeiteinträge eines bestimmten Zeitraums
GET /odata/TimeEntry?$filter=StartDateTime ge 2025-01-01T00:00:00Z and EndDateTime le 2025-01-31T23:59:59Z
Zeiteintrag erstellen
POST /odata/TimeEntry
Content-Type: application/json
{
"DisplayName": "Entwicklung API-Modul",
"ProjectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"StartDateTime": "2025-01-15T09:00:00Z",
"EndDateTime": "2025-01-15T12:30:00Z",
"IsBillable": true,
"PerformedByContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Das Feld DurationMinutes wird serverseitig aus StartDateTime und EndDateTime berechnet. Sie können es auch manuell setzen, wenn Sie keine Start-/Endzeit angeben.
Zeiteinträge nach Kontakt
GET /odata/TimeEntry?$filter=PerformedByContactId eq 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'&$top=50&$skip=0&$orderby=StartDateTime desc
C#-Beispiel
using System.Net.Http;
using System.Net.Http.Headers;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
// Zeiteinträge für April 2025 abfragen
var response = await client.GetAsync(
"https://{tenant}.inloox.app/odata/TimeEntry?" +
$"$filter=ProjectId eq {projectId}" +
" and StartDateTime ge 2025-04-01T00:00:00Z" +
" and EndDateTime le 2025-04-30T23:59:59Z" +
"&$select=TimeEntryId,StartDateTime,EndDateTime,DurationMinutes,IsBillable" +
"&$orderby=StartDateTime asc");
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
// Zeiteintrag erstellen
var payload = new StringContent(
"""
{
"ProjectId": "{project-guid}",
"StartDateTime": "2025-04-15T09:00:00Z",
"EndDateTime": "2025-04-15T12:00:00Z",
"DescriptionHTML": "API-Integrationsarbeit",
"IsBillable": true
}
""",
System.Text.Encoding.UTF8,
"application/json");
var createResponse = await client.PostAsync(
"https://{tenant}.inloox.app/odata/TimeEntry", payload);
Filtern Sie Zeiteinträge für Auswertungen immer nach Datumsbereich (StartDateTime und EndDateTime), um nicht die gesamte Historie zu laden. Kombinieren Sie dies mit $select, um die Antwortgröße zu reduzieren.