Skip to content

Auto-Tracking API

All endpoints require authentication. Drafts and signals are scoped to the current user. The ingest endpoint uses service token authentication.

GET /api/auto-tracking/drafts

Permission: time / view

Query parameters:

ParamTypeDescription
date_fromstringFilter drafts from this date (YYYY-MM-DD)
date_tostringFilter drafts up to this date (YYYY-MM-DD)
statusstringFilter by status (default: pending). Use all for every status

Response: { drafts }

Each draft includes joined budget_name and task_title.

GET /api/auto-tracking/drafts/:id

Permission: time / view

Path parameters:

ParamTypeDescription
idstringDraft ID

Response: { draft, signals }

Returns the draft with its associated activity signals.

POST /api/auto-tracking/drafts/:id/accept

Permission: time / update

Accepts a pending draft and creates a time entry. Managers and above are auto-approved; employees/leads create a draft time entry.

Path parameters:

ParamTypeDescription
idstringDraft ID

Response: { time_entry_id, status }

POST /api/auto-tracking/drafts/:id/edit

Permission: time / update

Edits a pending draft’s fields, then creates a time entry from the merged values.

Path parameters:

ParamTypeDescription
idstringDraft ID

Request body:

FieldTypeDescription
hoursnumberOverride hours
descriptionstringOverride description
budget_idstring | nullOverride budget
task_idstring | nullOverride task
line_item_idstring | nullOverride line item
billablenumberOverride billable flag (0 or 1)

Response: { time_entry_id, status }

POST /api/auto-tracking/drafts/:id/dismiss

Permission: time / update

Dismisses a pending draft (marks it as dismissed).

Path parameters:

ParamTypeDescription
idstringDraft ID

Response: { ok: true }

POST /api/auto-tracking/drafts/accept-bulk

Permission: time / update

Accepts multiple pending drafts at once, creating time entries for each.

Request body:

FieldTypeDescription
idsstring[]Array of draft IDs to accept

Response: { accepted } — count of accepted drafts.

POST /api/auto-tracking/drafts/dismiss-bulk

Permission: time / update

Dismisses multiple pending drafts at once.

Request body:

FieldTypeDescription
idsstring[]Array of draft IDs to dismiss

Response: { dismissed } — count of dismissed drafts.

GET /api/auto-tracking/drafts/pending-count

Permission: time / view

Returns the number of pending drafts for the current user (used for sidebar badges).

Response: { pending_count }

GET /api/auto-tracking/signals

Permission: time / view

Query parameters:

ParamTypeDescription
date_fromstringFilter signals starting from this date (YYYY-MM-DD)
date_tostringFilter signals up to this date (YYYY-MM-DD)
sourcestringFilter by signal source (e.g. google_calendar, meetings, nucleus)

Response: { signals } — up to 200 signals, ordered by started_at descending.

GET /api/auto-tracking/preferences

Permission: time / view

Returns the current user’s auto-tracking preferences. Returns defaults if no preferences have been saved.

Response: { preferences }

Default preferences include enabled: 0, source toggles, default_rounding: "15min", and auto_dismiss_below_minutes: 5.

PUT /api/auto-tracking/preferences

Permission: time / update

Request body:

FieldTypeDescription
enablednumberEnable/disable auto-tracking (0 or 1)
source_google_calendarnumberTrack Google Calendar events
source_meetingsnumberTrack Nucleus meetings
source_nucleusnumberTrack Nucleus activity
source_githubnumberTrack GitHub activity
source_productivenumberTrack Productive activity
calendar_exclude_patternsstring[]Calendar event patterns to exclude
calendar_min_duration_minutesnumberMinimum event duration to track
custom_rulesunknown[]Custom categorisation rules
default_roundingstringRounding strategy (e.g. 15min)
auto_dismiss_below_minutesnumberAuto-dismiss signals shorter than this

Response: { ok: true }

POST /api/auto-tracking/ingest

Authentication: Service token via X-Service-Token header or Authorization: Bearer <token>. Does not use standard user authentication.

Bulk-ingests activity signals and/or time drafts from external agents.

Request body:

FieldTypeDescription
signalsarrayActivity signals to ingest
draftsarrayTime drafts to create

Each signal object:

FieldTypeDescription
idstringSignal ID
user_idstringTarget user
sourcestringSource system
source_idstringExternal ID
signal_typestringType of activity
titlestring | nullSignal title
started_atstring | nullStart timestamp
ended_atstring | nullEnd timestamp
duration_minutesnumber | nullDuration
metadatastring | nullJSON metadata
matched_budget_idstring | nullMatched budget
matched_task_idstring | nullMatched task

Each draft object:

FieldTypeDescription
idstringDraft ID
user_idstringTarget user
datestringDate (YYYY-MM-DD)
hoursnumberHours
descriptionstring | nullDescription
budget_idstring | nullBudget
task_idstring | nullTask
billablenumberBillable flag
signal_idsstringJSON array of signal IDs
signal_countnumberNumber of signals
match_confidencenumberAI confidence score
categorization_sourcestringHow it was categorised

Response: { signals_ingested, drafts_created }