API Reference

REST API for Time Tracker. Base URL: https://app.trackingtabs.com/api/v1

Getting started

1. Create a personal access token at Settings → API Tokens.

2. Include it in every request:

curl -H 'Authorization: Bearer tta_YOUR_TOKEN' \
  https://app.trackingtabs.com/api/v1/me

3. All responses are JSON. Errors return { "error": { "code": "...", "message": "..." } }

Auth

GET
/api/v1/me

Get the authenticated user and workspace

Returns the user and workspace associated with the bearer token. Useful for verifying the token works and resolving the workspace context.

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/me' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
401Missing or invalid token

Entries

GET
/api/v1/entries

List time entries

Returns time entries scoped to the token's workspace. Filters narrow the result; ordering is newest first by `start`. Members see only their own entries; admins and owners see all workspace entries.

Parameters

NameInRequiredDescription
fromqueryNoInclusive lower bound on `start`.
toqueryNoExclusive upper bound on `start`.
project_idqueryNoFilter to a single project.
billablequeryNoFilter to billable (true) or non-billable (false).
user_idqueryNoFilter to a specific user (admins/owners only; ignored for members).
limitqueryNoDefault 50, max 200.
offsetqueryNoFor pagination.

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/entries' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
401Unauthorized
429Rate limited
POST
/api/v1/entries

Create a time entry

Creates a time entry. If `stop` is omitted, this becomes the currently-running entry (any existing running entry is stopped at `start` of the new one). Pass `idempotency_key` to safely retry — duplicate keys return the original entry.

Example request

curl -X POST 'https://app.trackingtabs.com/api/v1/entries' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'
  -d '{
  "description": "Drafting Q2 retainer renewal",
  "project_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
  "tags": [
    "client-work",
    "writing"
  ],
  "start": "2026-05-24T14:00:00Z",
  "stop": "2026-05-24T15:30:00Z",
  "billable": true,
  "idempotency_key": "renewal-draft-2026-05-24"
}'

Responses

201Created
400Validation error
401Unauthorized
409Idempotency conflict
GET
/api/v1/entries/current

Get the currently-running entry

Returns the user's currently-running entry, or `null` if no timer is running.

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/entries/current' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
POST
/api/v1/entries/start

Start a new timer

Starts a new timer for the authenticated user. Atomically stops any existing running timer at the new entry's `start` time. Equivalent to `POST /entries` with `start = now()` and no `stop`.

Example request

curl -X POST 'https://app.trackingtabs.com/api/v1/entries/start' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'
  -d '{
  "description": "Code review",
  "project_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456"
}'

Responses

201Timer started
401Unauthorized
POST
/api/v1/entries/stop

Stop the running timer

Stops the currently-running entry for the authenticated user. Returns 404 if no timer is running.

Example request

curl -X POST 'https://app.trackingtabs.com/api/v1/entries/stop' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Stopped
404No running timer
PATCH
/api/v1/entries/{id}

Update a time entry

Patches fields on an existing entry. Members can only update their own entries; admins/owners can update any entry in the workspace.

Parameters

NameInRequiredDescription
idpathYesEntry ID.

Example request

curl -X PATCH 'https://app.trackingtabs.com/api/v1/entries/:id' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'
  -d '{
  "description": "Drafting Q2 retainer renewal (revised)",
  "billable": true
}'

Responses

200Updated
400Validation error
403Forbidden
404Not found
DELETE
/api/v1/entries/{id}

Delete a time entry

Deletes an entry permanently. Same access rules as update.

Parameters

NameInRequiredDescription
idpathYesEntry ID.

Example request

curl -X DELETE 'https://app.trackingtabs.com/api/v1/entries/:id' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

204Deleted
403Forbidden
404Not found

Projects

GET
/api/v1/projects

List projects

Returns projects visible to the user. Project visibility honors `project_members` restrictions: if any members are explicitly listed on a project, only those members (plus admins/owners) see it.

Parameters

NameInRequiredDescription
client_idqueryNoFilter to projects under a single client.
archivedqueryNoInclude archived projects (default false).

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/projects' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
POST
/api/v1/projects

Create a project

Creates a new project in the workspace. Requires admin or owner role.

Example request

curl -X POST 'https://app.trackingtabs.com/api/v1/projects' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'
  -d '{
  "name": "Dr. Rafii — Q2 Retainer",
  "client_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
  "color": "#3B82F6",
  "billable": true,
  "hourly_rate": 175,
  "currency": "USD"
}'

Responses

201Created
403Forbidden

Clients

GET
/api/v1/clients

List clients

Returns clients in the workspace.

Parameters

NameInRequiredDescription
archivedqueryNoInclude archived clients (default false).

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/clients' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
POST
/api/v1/clients

Create a client

Creates a new client. Requires admin or owner role.

Example request

curl -X POST 'https://app.trackingtabs.com/api/v1/clients' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'
  -d '{
  "name": "LVC Beverly Hills"
}'

Responses

201Created
403Forbidden

Tags

GET
/api/v1/tags

List tags

Returns all tags in the workspace.

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/tags' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success

Reports

GET
/api/v1/reports/summary

Get a summary report

Aggregates time entries in the given date range grouped by the chosen dimension. Returns totals (seconds + billable amount in workspace currency) and a per-group breakdown.

Parameters

NameInRequiredDescription
fromqueryYesInclusive lower bound on `start`.
toqueryYesExclusive upper bound on `start`.
group_byqueryNoGrouping dimension (default: project).
billablequeryNoFilter to billable or non-billable.

Example request

curl -X GET 'https://app.trackingtabs.com/api/v1/reports/summary' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json'

Responses

200Success
400Validation error

Error codes

unauthorizedMissing or invalid bearer token
forbiddenToken lacks permission for this action
not_foundRequested resource does not exist
validation_errorRequest body or query params failed validation
conflictDuplicate resource or conflicting state
rate_limitedToo many requests — slow down
feature_gatedFeature requires a higher plan
internal_errorUnexpected server error

14 endpoints · sourced from lib/api-spec.ts