Time Entries
The TimeEntry entity represents recorded time against a project. Time entries track who worked on what, for how long, and whether the work is billable. They can be linked to tasks, planning phases, and documents.
All endpoints use the base path /odata/TimeEntry. Comments are managed via /odata/TimeEntryComment. For the flattened list view, use /odata/DynamicTimeEntry which returns all standard properties plus any user-defined fields.
Data Model
| Property | Type | Description |
|---|---|---|
TimeEntryId | guid | Unique identifier of the time entry. |
DisplayName | string | Auto-generated display name (read-only). |
StartDateTime | datetime | Start date and time of the recorded work. |
EndDateTime | datetime | End date and time of the recorded work. |
ProjectId | guid? | ID of the associated project. |
DescriptionHTML | string | HTML-formatted description of the work performed. |
DescriptionText | string | Plain-text description of the work performed. |
PhaseId | guid? | ID of the planning phase this entry is associated with. |
IsBillable | bool | Whether this time entry is billable to the client. |
PerformedByContactId | guid? | ID of the contact who performed the work. |
ColorFlag | int? | Color flag for visual categorization. |
GroupId | guid? | ID of the time entry group. |
TaskItemId | guid? | ID of the linked task, if any. |
IsBilled | bool | Whether this time entry has been invoiced. |
DurationMinutes | double? | Duration in minutes (computed from start/end, read-only). |
Endpoints
CRUD Operations
/odata/TimeEntryList all time entries
Returns all time entries the authenticated user has access to. Supports OData query options such as $filter, $select, $orderby, $top, and $skip.
/odata/TimeEntry({key})Get a single time entry by ID
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The unique time entry ID. |
/odata/TimeEntryCreate a new time entry
{
"ProjectId": "project-guid",
"StartDateTime": "2025-04-01T09:00:00Z",
"EndDateTime": "2025-04-01T11:30:00Z",
"DescriptionText": "Frontend development — login page",
"IsBillable": true,
"PerformedByContactId": "contact-guid"
}
If PerformedByContactId is omitted, the time entry is recorded for the authenticated user.
/odata/TimeEntry({key})Update an existing time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID to update. |
Send only the properties you want to change:
{
"EndDateTime": "2025-04-01T12:00:00Z",
"IsBillable": false
}
/odata/TimeEntry({key})Delete a time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID to delete. |
Deleting a time entry is permanent. If the entry has been billed, ensure your billing records are updated accordingly.
/odata/TimeEntry/$countGet total number of time entries
Returns the count as a plain integer. Supports $filter to count a subset.
Special Operations
/odata/TimeEntry/GetCalendarTimeEntriesForProject(projectId={projectId},take={take})Get calendar-formatted time entries for a project
| Parameter | Type | Required | Description |
|---|---|---|---|
projectId | guid | ✅ | The project ID to retrieve time entries for. |
take | int | ✅ | Maximum number of entries to return. |
Returns time entries formatted for calendar display.
/odata/TimeEntry/CreateTimeEntryFromGraphEventCreate a time entry from a Microsoft Graph calendar event
Converts a Microsoft 365 calendar event into an InLoox time entry.
{
"GraphEventId": "graph-event-id",
"ProjectId": "project-guid",
"IsBillable": true
}
This endpoint requires Microsoft Graph integration to be configured in your InLoox environment.
/odata/TimeEntry({key})/CopyCreate a copy of the time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The source time entry ID to copy. |
Returns the newly created time entry.
/odata/TimeEntry({key})/CopyWithNewDatesCopy a time entry with different start/end dates
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The source time entry ID to copy. |
{
"StartDateTime": "2025-04-02T09:00:00Z",
"EndDateTime": "2025-04-02T11:30:00Z"
}
Documents
/odata/TimeEntry({key})/AddDocumentToTimeEntryLink a document to the time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID. |
{
"DocumentId": "document-guid"
}
/odata/TimeEntry({key})/RemoveDocumentFromTimeEntryRemove a document link from the time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID. |
{
"DocumentId": "document-guid"
}
Relations
/odata/TimeEntry({key})/AddRelationAdd a relation to another entity
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID. |
{
"TargetId": "target-entity-guid",
"RelationType": "RelatedTo"
}
/odata/TimeEntry({key})/RemoveRelationRemove an existing relation
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID. |
{
"RelationId": "relation-guid"
}
Notes
/odata/TimeEntry({key})/AddNoteAdd a note to the time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The time entry ID. |
{
"Text": "Includes pair programming session with backend team."
}
/odata/TimeEntry/DeleteNote(noteRelationId={noteRelationId})Delete a note from a time entry
| Parameter | Type | Required | Description |
|---|---|---|---|
noteRelationId | guid | ✅ | The note relation ID to delete. |
Custom Fields — DynamicTimeEntry
Use the DynamicTimeEntry endpoint to access time entries with custom fields:
GET /odata/DynamicTimeEntry
GET /odata/DynamicTimeEntry({key})
Custom field names follow the pattern CF_<FieldName>.
/odata/DynamicTimeEntryFlattened time entry view with project, planning, and task data
/odata/DynamicTimeEntry/$countGet total number of DynamicTimeEntry records
DynamicTimeEntry only supports GET requests. To create or update time entries, use the regular /odata/TimeEntry endpoints.
TimeEntryComment Sub-Entity
Time entries can have comments attached. Comments are accessed through the TimeEntryComment entity:
Properties
| Property | Type | Description |
|---|---|---|
TimeEntryCommentId | guid | Unique identifier of the comment. |
TimeEntryId | guid | ID of the parent time entry. |
Comment | string | Comment text (plain text). |
CommentHtml | string | Comment text (HTML). |
ShortDescription | string | Short description. |
CreateDateTime | datetime | When the comment was created. |
CreatedByContactId | guid | ID of the contact who created the comment. |
# Get comments for a specific time entry
curl -X GET "https://{tenant}.inloox.app/odata/TimeEntryComment?\
$filter=TimeEntryId eq {time-entry-guid}" \
-H "Authorization: Bearer {token}"
TimeEntryComment Endpoints
/odata/TimeEntryCommentList all time entry comments
/odata/TimeEntryCommentCreate a new comment
| Parameter | Type | Required | Description |
|---|---|---|---|
Body | Delta<ApiTimeEntryComment> | ✅ | JSON object with the comment data. |
/odata/TimeEntryComment({key})Get a single comment by ID
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The TimeEntryCommentId. |
/odata/TimeEntryComment({key})Update a comment
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The TimeEntryCommentId. |
Body | Delta<ApiTimeEntryComment> | ✅ | JSON object with the fields to update. |
/odata/TimeEntryComment({key})Delete a comment
| Parameter | Type | Required | Description |
|---|---|---|---|
key | guid | ✅ | The TimeEntryCommentId. |
/odata/TimeEntryComment/$countGet total number of comments
OData Query Examples
Filter by Project and Date Range
curl -X GET "https://{tenant}.inloox.app/odata/TimeEntry?\
$filter=ProjectId eq {project-guid}\
and StartDateTime ge 2025-04-01T00:00:00Z\
and EndDateTime le 2025-04-30T23:59:59Z\
&$select=TimeEntryId,DisplayName,StartDateTime,EndDateTime,DurationMinutes,IsBillable\
&$orderby=StartDateTime desc" \
-H "Authorization: Bearer {token}"
Billable Time Entries Only
curl -X GET "https://{tenant}.inloox.app/odata/TimeEntry?\
$filter=IsBillable eq true and IsBilled eq false\
&$orderby=StartDateTime asc" \
-H "Authorization: Bearer {token}"
Time Entries by Contact
curl -X GET "https://{tenant}.inloox.app/odata/TimeEntry?\
$filter=PerformedByContactId eq {contact-guid}\
&$top=50&$skip=0\
&$orderby=StartDateTime desc" \
-H "Authorization: Bearer {token}"
C# Example
using System.Net.Http;
using System.Net.Http.Headers;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
// Query time entries for April 2025
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);
// Create a time entry
var payload = new StringContent(
"""
{
"ProjectId": "{project-guid}",
"StartDateTime": "2025-04-15T09:00:00Z",
"EndDateTime": "2025-04-15T12:00:00Z",
"DescriptionText": "API integration work",
"IsBillable": true
}
""",
System.Text.Encoding.UTF8,
"application/json");
var createResponse = await client.PostAsync(
"https://{tenant}.inloox.app/odata/TimeEntry", payload);
When querying time entries for reporting, always filter by date range (StartDateTime and EndDateTime) to avoid loading the entire history. Combine with $select to reduce payload size.