Start a timer
POSThttps://
Starts a stopwatch on a work item or a planning event for the authenticated user and returns it with a Location header.
Access
- Token scope
- api:
write: hours Without it:
403 insufficient-token-scope. - Permission
- None. The record's own rules still apply.
- Rate cost
- 1 unit, write bucket. A write costs the same whatever
viewyou ask for. - Also
- Accepts
Idempotency-Key. Never cached:private, no-store. Unknown body keys are refused, never dropped.
Both are checked, scope first. A token never does more than its user. How access is checked
user_id is not accepted: a timer always belongs to the caller, and there is no way to start one for another employee. Send timeable_type and timeable_id together; omit started_at to start now. A second timer on the same record for the same caller is a 422 with code unique (there is at most one timer per employee per record), so Idempotency-Key is optional here rather than required: a retry meets that rule anyway. There is no stop action: to book the elapsed minutes, read started_at, POST the hours to /api/v2/worklogs and then DELETE this timer. Those two calls are not atomic: a client that deletes first loses the minutes, and one that crashes between them leaves the timer running. This operation declares no permission of its own, and a caller can only ever create their own timer. plnnrly also hides its Start button on a record you may not log time on; the API does not check that when the timer starts. Nothing unbillable can be booked that way regardless: POST /api/v2/worklogs applies that gate when the hours are actually written.
Query parameters
Unknown parameters are refused with 400, naming the parameter.
Request headers
A correlation id of your own. It is recorded in our logs next to the server's request id but never returned: the response header always carries the server's id. A value that does not match the pattern is discarded silently, never rejected.
Request body
Unknown keys are refused with 422, naming the key.
The record being timed. Expanding it with ?include=timeable additionally requires the read permission and token scope of the target's own prefix, per branch: project_management for a work item, events for a planning event.
work_itemevent
The record being timed. Expanding it with ?include=timeable additionally requires the read permission and token scope of the target's own prefix, per branch: project_management for a work item, events for a planning event.
Required when timeable_type is present. Must be unique across Timer.
Response 201
Returns a Timer in the detail view.
Headers
ETag- A strong validator of exactly this representation.
Idempotency-Replayedtruewhen this response was replayed from a storedIdempotency-Keyrather than produced by a new write.Location- The absolute URL of the created or queued resource.
RateLimit- The IETF
httpapi-ratelimit-headersform of your remaining allowance on the tightest bucket this request touched. RateLimit-Policy- The ceiling and window of that bucket, as
<limit>;w=<seconds>. X-Request-Id- The server-generated ULID correlating this response with our logs.
Every response also carries Cache-Control, Vary, X-Content-Type-Options, X-Plnnrly-Api-Version, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Headers and versioning
Employee this timer belongs to. Always the authenticated user; a timer cannot be started for someone else.
The employee this timer belongs to. Expanding it with ?include=user additionally requires the users::read permission and a token scope covering the users prefix.
The kind of record timeable points at; it says which branch of timeable applies.
work_itemevent
New values may be added.
The record being timed. Expanding it with ?include=timeable additionally requires the read permission and token scope of the target's own prefix, per branch: project_management for a work item, events for a planning event.
Which form you get depends on timeable_type.
work_itemWorkItemSummaryeventEventSummary
When the stopwatch was started. Elapsed time is this value against the client's own clock; the API publishes no elapsed counter.
Errors
409 Conflict.
415 Unsupported media type.
422 Unprocessable content.
7 errors every operation can return: 400, 401, 404, 406, 429, 500, 503
400 Bad request.
idempotency-key-requiredinvalid-cursorinvalid-query-parametermalformed-requestunsupported-parameter
401 Unauthenticated.
404 Not found.
406 Not acceptable.
429 Too many requests.
500 Server error.
503 Service unavailable.
This path allows GET, POST. Anything else answers 405.
Something wrong or missing on this page? Tell us