{"openapi":"3.1.0","info":{"title":"TrackTimer REST API","version":"1.0.0","description":"Personal, workspace-bound time tracking. All operations require a bearer API key and the documented scope. Access follows current workspace membership and assigned projects. All seven operations share a per-key limit of 120 requests per 60 seconds. This specification covers the public REST API; hosted MCP has separate OAuth authentication and capabilities."},"servers":[{"url":"https://www.tracktimer.app"}],"externalDocs":{"description":"TrackTimer API documentation","url":"https://www.tracktimer.app/docs"},"security":[{"bearerAuth":[]}],"paths":{"/api/v1/projects":{"post":{"operationId":"createProject","summary":"Create a project","description":"Create a project as a workspace admin and automatically join it. Required scope: projects:write.","x-required-scope":"projects:write","externalDocs":{"url":"https://www.tracktimer.app/docs/create-project"},"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"color":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":200}},"required":["clientId","name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"project":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"}},"required":["id","clientId","name","color"],"additionalProperties":false}},"required":["project"],"additionalProperties":false}}}},"400":{"description":"INVALID_REQUEST, INVALID_CURSOR (time-entry pagination), or IDEMPOTENCY_KEY_REQUIRED (mutations). Fix the input before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"RESOURCE_NOT_FOUND: client is unknown, archived, or outside the workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: creation may have succeeded. List projects and reconcile; do not automatically retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listProjects","summary":"List projects for a client","description":"Find assigned, unarchived projects for a client in the key’s workspace. Required scope: projects:read.","x-required-scope":"projects:read","externalDocs":{"url":"https://www.tracktimer.app/docs/list-projects"},"parameters":[{"name":"clientId","in":"query","required":true,"description":"Client to list projects for.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"}},"required":["id","clientId","name","color"],"additionalProperties":false}}},"required":["projects"],"additionalProperties":false}}}},"400":{"description":"INVALID_REQUEST, INVALID_CURSOR (time-entry pagination), or IDEMPOTENCY_KEY_REQUIRED (mutations). Fix the input before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/clients":{"get":{"operationId":"listClients","summary":"List clients","description":"Discover active workspace clients according to the API key owner’s role. Required scope: clients:read.","x-required-scope":"clients:read","externalDocs":{"url":"https://www.tracktimer.app/docs/list-clients"},"parameters":[],"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"clients":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"}},"required":["id","name","color"],"additionalProperties":false}},"canCreateProjects":{"default":false,"type":"boolean"}},"required":["clients","canCreateProjects"],"additionalProperties":false}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/timer":{"get":{"operationId":"getActiveTimer","summary":"Get the active timer","description":"Read the key owner’s current timer in the bound workspace. Required scope: timers:read.","x-required-scope":"timers:read","externalDocs":{"url":"https://www.tracktimer.app/docs/get-active-timer"},"parameters":[],"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"timer":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientName":{"type":"string","minLength":1},"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"projectName":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"billable":{"type":"boolean"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"serverNow":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"elapsedSeconds":{"type":"integer","minimum":0,"maximum":2147483647},"payRateCents":{"type":"integer","minimum":0,"maximum":2147483647},"currency":{"type":"string","const":"USD"}},"required":["id","clientId","clientName","projectId","projectName","color","billable","note","startedAt","serverNow","elapsedSeconds","payRateCents","currency"],"additionalProperties":false},{"type":"null"}]}},"required":["timer"],"additionalProperties":false}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/timers/start":{"post":{"operationId":"startTimer","summary":"Start or switch a timer","description":"Start a project timer and atomically complete any timer already running for the user. Required scope: timers:write. Starting a timer can stop your existing active timer.","x-required-scope":"timers:write","externalDocs":{"url":"https://www.tracktimer.app/docs/start-timer"},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Persist a fresh unique identifier for each intended mutation. The trimmed value must contain 1–255 characters. Retry uncertain requests with the same key and input; successful replays return the original response snapshot. Never intentionally recycle keys.","schema":{"type":"string","minLength":1,"maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"billable":{"default":true,"type":"boolean"},"note":{"type":"string","maxLength":500}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"timer":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientName":{"type":"string","minLength":1},"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"projectName":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"billable":{"type":"boolean"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"serverNow":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"elapsedSeconds":{"type":"integer","minimum":0,"maximum":2147483647},"payRateCents":{"type":"integer","minimum":0,"maximum":2147483647},"currency":{"type":"string","const":"USD"}},"required":["id","clientId","clientName","projectId","projectName","color","billable","note","startedAt","serverNow","elapsedSeconds","payRateCents","currency"],"additionalProperties":false},{"type":"null"}]},"stoppedTimerId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["timer","stoppedTimerId"],"additionalProperties":false}}}},"400":{"description":"INVALID_REQUEST, INVALID_CURSOR (time-entry pagination), or IDEMPOTENCY_KEY_REQUIRED (mutations). Fix the input before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"PROJECT_NOT_FOUND: project is not accessible or ready for tracking.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"IDEMPOTENCY_CONFLICT: key reused with different input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/timers/{timerId}/stop":{"post":{"operationId":"stopTimer","summary":"Stop a timer","description":"Complete a timer owned by the key user in the bound workspace. Required scope: timers:write.","x-required-scope":"timers:write","externalDocs":{"url":"https://www.tracktimer.app/docs/stop-timer"},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Persist a fresh unique identifier for each intended mutation. The trimmed value must contain 1–255 characters. Retry uncertain requests with the same key and input; successful replays return the original response snapshot. Never intentionally recycle keys.","schema":{"type":"string","minLength":1,"maxLength":255}},{"name":"timerId","in":"path","required":true,"description":"Your timer entry ID.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"timer":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientName":{"type":"string","minLength":1},"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"projectName":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"billable":{"type":"boolean"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"serverNow":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"elapsedSeconds":{"type":"integer","minimum":0,"maximum":2147483647},"payRateCents":{"type":"integer","minimum":0,"maximum":2147483647},"currency":{"type":"string","const":"USD"}},"required":["id","clientId","clientName","projectId","projectName","color","billable","note","startedAt","serverNow","elapsedSeconds","payRateCents","currency"],"additionalProperties":false},{"type":"null"}]},"stoppedTimerId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["timer","stoppedTimerId"],"additionalProperties":false}}}},"400":{"description":"INVALID_REQUEST, INVALID_CURSOR (time-entry pagination), or IDEMPOTENCY_KEY_REQUIRED (mutations). Fix the input before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"TIMER_NOT_FOUND: timer does not exist or is not yours in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"IDEMPOTENCY_CONFLICT, TIMER_VOIDED, or TIMER_ALREADY_STOPPED. Reconcile state before another operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/time-entries":{"get":{"operationId":"listTimeEntries","summary":"List personal time entries","description":"Read personal workspace history with project filtering and cursor pagination. Required scope: timers:read.","x-required-scope":"timers:read","externalDocs":{"url":"https://www.tracktimer.app/docs/list-time-entries"},"parameters":[{"name":"projectId","in":"query","required":false,"description":"Filter your entries by project.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"cursor","in":"query","required":false,"description":"Opaque nextCursor from the preceding page. Omit for the first page; null nextCursor means no more pages.","schema":{"type":"string","minLength":1,"maxLength":1024,"pattern":"^[A-Za-z0-9_-]+$"}},{"name":"limit","in":"query","required":false,"description":"Maximum entries per page; defaults to 20.","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Successful response. JSON is returned directly without a data envelope.","headers":{"X-Request-Id":{"description":"Request identifier for investigation.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"clientName":{"type":"string","minLength":1},"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"projectName":{"type":"string","minLength":1},"color":{"default":"#ff5c35","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"status":{"type":"string","enum":["active","completed","voided"]},"billable":{"type":"boolean"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"endedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"durationSeconds":{"anyOf":[{"type":"integer","minimum":0,"maximum":2147483647},{"type":"null"}]},"payRateCents":{"type":"integer","minimum":0,"maximum":2147483647},"earnings":{"anyOf":[{"type":"string","pattern":"^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$"},{"type":"null"}]},"currency":{"type":"string","const":"USD"}},"required":["id","clientId","clientName","projectId","projectName","color","status","billable","note","startedAt","endedAt","durationSeconds","payRateCents","earnings","currency"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string","minLength":1,"maxLength":1024,"pattern":"^[A-Za-z0-9_-]+$"},{"type":"null"}]}},"required":["entries","nextCursor"],"additionalProperties":false}}}},"400":{"description":"INVALID_REQUEST, INVALID_CURSOR (time-entry pagination), or IDEMPOTENCY_KEY_REQUIRED (mutations). Fix the input before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"INVALID_API_KEY: missing, malformed, expired, revoked, or no longer bound to valid workspace membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"INSUFFICIENT_SCOPE: the key lacks the required scope. FORBIDDEN: project creation requires an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API_KEY_RATE_LIMITED: pause for the rate-limit window and reduce request frequency. Retry-After is not currently provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"INTERNAL_ERROR: keep requestId for investigation. Retry timer mutations only with the same idempotency key and input using bounded backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Personal API key created in workspace Settings. Browser session cookies and query parameters do not authenticate this API."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$"},"message":{"type":"string","minLength":1},"details":{"default":{},"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["code","message","details"],"additionalProperties":false},"requestId":{"type":"string","minLength":1}},"required":["error","requestId"],"additionalProperties":false}}}}