Stop a timer
Complete a timer owned by the key user in the bound workspace.
POST /api/v1/timers/{timerId}/stop
Required scope: timers:write
Stops an entry with a server-generated end timestamp and duration. The target must belong to this user and workspace.
Request
Requires bearer authentication, timers:write, and Idempotency-Key of 1–255 characters after trimming. timerId is a required UUID path parameter. The endpoint does not read a request body: send no body. It cannot update notes or accept an end timestamp.
Use the ID returned by the active-timer endpoint. Persist a stop operation ID in $TRACKTIMER_OPERATION_ID, distinct from the start ID.
curl --request POST "https://www.tracktimer.app/api/v1/timers/33333333-3333-4333-8333-333333333333/stop" \
--header "Authorization: Bearer $TRACKTIMER_API_KEY" \
--header "Idempotency-Key: $TRACKTIMER_OPERATION_ID"
Response — 200
timer: alwaysnullin this response.stoppedTimerId: UUID of the specified stopped or already completed entry.
{
"timer": null,
"stoppedTimerId": "33333333-3333-4333-8333-333333333333"
}
Read time-entry history for completed duration and earnings. timer:null is a mutation result, not the current global timer state. Another timer can still be running if this target was already completed by a switch.
Completed, voided, and inaccessible targets
An already completed target normally succeeds without changing its end time, including with a new stop ID. Replaying a successful receipt does not extend it. A fresh stop on a voided entry returns 409 TIMER_VOIDED; an existing successful receipt can still replay after the entry is voided.
Unknown, other-user, or other-workspace targets return 404 TIMER_NOT_FOUND. Invalid UUIDs return 400 INVALID_REQUEST. Reusing a stop key for a different accessible target returns 409 IDEMPOTENCY_CONFLICT. A failed open-entry update can return 409 TIMER_ALREADY_STOPPED. See shared errors.