Gipo
Resources

Time entries

Log and adjust manual time on tasks and subtasks.

A time entry records work time against a task or subtask on one calendar day. There is at most one entry per (person, task or subtask, date): posting more time on the same day merges into the existing entry — summing the duration and stacking the new description on top — rather than creating a second row. Manual entries are posted via this API; entries produced by the in-app timer are server-generated and not creatable via REST.

Endpoints

MethodPathNotes
GET/api/v1/time-entriesList with filters. Cursor pagination.
POST/api/v1/time-entriesLog a manual entry. Accepts Idempotency-Key.
GET/api/v1/time-entries/{id}Single entry with user, task, subtask.
PATCH/api/v1/time-entries/{id}Edit description, start time, duration.
DELETE/api/v1/time-entries/{id}Delete the entry.

The in-app timer endpoints (start, stop, switch) are intentionally not exposed via REST in v1.

TimeEntry model

{
  "id": "e1…",
  "organizationId": "...",
  "userId": "u1…",
  "taskId": "t1…",
  "subtaskId": null,
  "description": "Initial wiring",
  "date": "2026-05-19",
  "durationSeconds": 5400,
  "source": "manual",
  "autoStopped": false,
  "createdAt": "...",
  "updatedAt": "..."
}
FieldNotes
dateThe work day this time counts for (YYYY-MM-DD). One entry per person/task/day.
sourcemanual (this API) or timer (in-app start/stop). A day mixing both reads as manual.
autoStoppedtrue when the 8h-cap sweeper persisted a timer-driven entry.

Each entry belongs to exactly one of taskId or subtaskId (XOR). The parent is immutable after creation.

Listing entries

GET /api/v1/time-entries?userId=...&startDate=2026-05-01&endDate=2026-05-31
ParamTypeNotes
userIdUUIDOne member's entries.
taskIdUUIDDirect task entries.
subtaskIdUUIDSubtask entries.
projectIdUUIDEntries on tasks/subtasks of one project.
startDatedateInclusive lower bound on date (the work day).
endDatedateInclusive upper bound on date (the work day).
cursorUUIDFrom a previous response.
limitint 1–100Default 50.

Returns { data, pagination: { nextCursor } }. Entries are filtered by project visibility — standard members may not see entries on tasks they cannot access.

Logging a manual entry

POST /api/v1/time-entries
Content-Type: application/json
Idempotency-Key: ...

{
  "taskId": "t1…",
  "date": "2026-05-19",
  "durationSeconds": 5400,
  "description": "Initial wiring"
}

Required:

FieldTypeConstraint
Exactly one of taskId or subtaskIdUUIDSending both, or neither, returns 422.
datedateThe work day (YYYY-MM-DD). Must not be in the future.
durationSecondsint1 – 86 400 (≤ 24 h).

Optional:

FieldTypeConstraint
descriptionstring≤ 50 000 chars (rich-text HTML).
timezonestringIANA zone for the future-date guard and the stacked block's time label. Defaults to UTC.

Response: 201 Created with the entry — whether a new entry was created or the time merged into an existing one for that person/task/day. The entry is always attributed to the API key's user.

Editing an entry

PATCH /api/v1/time-entries/{id}
{ "durationSeconds": 7200 }

Caller must be one of:

  • The entry's author, or
  • An organization owner / admin, or
  • A project manager on the entry's parent project.

Allowed fields: description, date, durationSeconds. Moving date onto a day that already holds this person's entry for the same task/subtask returns 409.

Deleting an entry

DELETE /api/v1/time-entries/{id}

Returns { "data": { "success": true } }. Same authorization rules as edit.

Common precondition failures

CodeCause
422Body sent both taskId and subtaskId, or neither.
403Caller can read the entry but cannot edit/delete it.
404Cross-org id, or entry belongs to a task the caller cannot access.
409PATCH moved date onto a day that already holds this person's entry for the same task/subtask.
412The parent task is finalized or blocked, so it is read-only.
412The parent task's project is closed (completed / cancelled). POST and PATCH are rejected — those hours would fall outside the billing cycle — including on tasks linked before the project closed. DELETE is still allowed, so wrongly-logged hours can be removed.

On this page