Where Time Tracking shows up across the rest of Leenops, plus webhooks, AI tools, and the public REST API.
Time Tracking is connective tissue. This page lists every place it surfaces inside other modules, and every external integration point (webhooks, AI, public API).
Read-only view of utilization (lights up only when the People module is subscribed).
Soft dependency
The People module's employees.weekly_hours is used as the utilization denominator. Without People, falls back to time_tracking_settings.default_weekly_hours.
The settings UI includes a Test button per webhook. It fires a synthetic webhook.test event so you can verify your endpoint receives + signs correctly without waiting for a real event.
For automation tools that need to register webhooks without going through the UI:
Method
Path
Purpose
POST
/api/v1/time/webhooks
Create a webhook subscription. Body: { url, events[], secret?, enabled? }. Returns { id, url, events, enabled, created_at, secret } — the secret is returned only once on create; store it for HMAC verification.
DELETE
/api/v1/time/webhooks/{id}
Delete a subscription.
Both endpoints use the standard v1 bearer-token auth. This pair is the surface a Zapier app (or any external automation) consumes — the user pastes their API token into Zapier's connection screen, Zapier POSTs to subscribe, receives the secret, and uses it to verify every payload signature.
Ten time tools are auto-discovered by the AI chat (/api/ai/chat) and the MCP server.
Tool
Type
What it does
get_active_timer
read
Returns the running entry (or null)
get_my_timesheet
read
Current week (or specified period_start)
get_utilization
read
Stats for a user / project / range — Pro
log_time_entry
write
Manual entry — needs entity_type, hours, log_date
start_timer
write
Starts a timer; auto-stops any running timer for the user
stop_timer
write
Stops the user's active timer
submit_timesheet
write
Submit a draft timesheet for the given week
approve_timesheet
write
Approve a submitted timesheet
reject_timesheet
write
Reject with a reason
convert_time_to_invoice_lines
write
Pull approved billable hours onto an invoice — Pro
Write tools always return requires_confirmation: true with the prepared payload. The user sees a confirmation card in the chat UI, approves, and the mutation runs client-side (so the user's auth + permissions apply, not the AI's).
Examples:
"How many billable hours did I log this week?" → get_my_timesheet → answer + breakdown
"Start a timer on the Acme onboarding ticket" → start_timer (write — confirms first)
"Pull last month's billable hours for Acme onto invoice INV-2026-042" → convert_time_to_invoice_lines (write — preview + confirm)
All endpoints under /api/v1/. Bearer-auth via Supabase session token. Standard v1 response envelope: { data, pagination? } for success, { error: { code, message } } for errors. X-API-Version: v1 header on every response.
State-transition endpoints enforce the same status-precondition guards as the UI — calling approve on a draft timesheet returns a 4xx with a clear error.