Start an empty time tracker
ACTUAL behaviour: the body binds to the base model, so the server builds a tracker with no task or absence (EntityType NotSpecified), and the domain check rejects it with 60071 (HTTP 500, Code 102). Before that rejection the caller's running tracker, if any, has already been stopped and converted into a time registration. Use the task or absence start operations instead.
Not for:
- Starting a tracker on a task: use
POST /v1/time-tracker/task/start-time-tracker. - Starting a tracker on an absence code: use
POST /v1/time-tracker/absence/start-time-tracker.
Behaviour:
- Not idempotent.
- Not safe to retry blindly.
- On failure: Stops the caller's running tracker (ended at the server's 'now') and converts it into time registration(s) — before the call fails with 60071. No new tracker is created.
- Read-after-write consistency: not yet documented.
See also: POST /v1/time-tracker/task/start-time-tracker, POST /v1/time-tracker/absence/start-time-tracker
Not yet documented: behaviour → consistency; behaviour → side effects on failure.
curl -X POST "https://app3.timelog.com/your-account/api/v1/time-tracker" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"Comment": "null",
"Minute": 42,
"TimeRegistrationID": "null"
}'
import requests
import json
url = "https://app3.timelog.com/your-account/api/v1/time-tracker"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"Comment": "null",
"Minute": 42,
"TimeRegistrationID": "null"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://app3.timelog.com/your-account/api/v1/time-tracker", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
"Comment": "null",
"Minute": 42,
"TimeRegistrationID": "null"
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"Comment": "null",
"Minute": 42,
"TimeRegistrationID": "null"
}`)
req, err := http.NewRequest("POST", "https://app3.timelog.com/your-account/api/v1/time-tracker", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://app3.timelog.com/your-account/api/v1/time-tracker')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request.body = '{
"Comment": "null",
"Minute": 42,
"TimeRegistrationID": "null"
}'
response = http.request(request)
puts response.body
{
"Properties": {
"TimeTrackerID": 123,
"ID": "123e4567-e89b-12d3-a456-426614174000",
"UserID": 123,
"Date": "2024-12-25T10:00:00Z",
"StartTime": "2024-12-25T10:00:00Z",
"EntityType": 42,
"EntityID": "null",
"Task": {
"TaskID": 123,
"ID": "123e4567-e89b-12d3-a456-426614174000",
"Name": "John Doe",
"No": "example_string",
"IsFixedPrice": true,
"IsDefaultBillable": true,
"AdditionalTextIsRequired": true,
"ParentFullName": "John Doe",
"ProjectID": 123,
"Project": {
"ProjectID": 123,
"ID": "123e4567-e89b-12d3-a456-426614174000",
"Name": "John Doe",
"No": "example_string",
"ExpenseIsBillable": "null",
"CustomerID": 123,
"Customer": {
"CustomerID": 123,
"ID": "123e4567-e89b-12d3-a456-426614174000",
"Name": "John Doe",
"No": "example_string",
"DefaultMileageDistance": 25,
"CustomerStatusID": 123,
"VATNo": "example_string",
"OrganizationNo": "example_string"
},
"MainContractId": 123
},
"ParentTaskID": "null",
"IsTravelTimeTask": true,
"IsFavourite": "null"
},
"AbsenceCode": {
"AbsenceCodeID": 123,
"AbsenceCode": "example_string",
"Name": "John Doe",
"Description": "example_string",
"IsActive": true,
"FlexPositiveFactor": 3.14,
"SalaryAccountFactor": 3.14,
"SalaryAccountFactorEffect": 10,
"SalaryAccountID": 123,
"AbsenceCodeTypeID": 123,
"DeductCapacity": true,
"TimeTrackingFormat": 42,
"RequireApproval": true,
"IsPublicVisible": true,
"IsFavourite": "null",
"ID": "123e4567-e89b-12d3-a456-426614174000"
},
"TimeRegistrationID": "null",
"Comment": "example_string",
"Minute": 42,
"BillableMinute": 42,
"IsBillable": "null",
"TimeTrackerStatus": 42,
"MonthlyPeriod": "null",
"AdditionalTextField": "null",
"Factor": 3.14
},
"Links": [
{
"Href": "example_string",
"Rel": "example_string"
}
],
"Actions": [
{}
]
}
{
"error": "Bad Request",
"message": "The request contains invalid parameters or malformed data",
"code": 400,
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Internal Server Error",
"message": "An unexpected error occurred on the server",
"code": 500,
"requestId": "req_1234567890"
}
/v1/time-tracker
Target server for requests. Edit to use your own host.
OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp).
The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user.
> Not yet documented: how to obtain a token.
> Not yet documented: token lifetime.
Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp).
The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user.
> Not yet documented: how to obtain a token.
> Not yet documented: token lifetime.The media type of the request body
Unit: minutes
Refers to TimeRegistrationRead.TimeRegistrationID. Look up valid values with GET /v1/time-registration/{timeRegistrationID}.
- Always (POST /v1/time-tracker) — The default adapter branch never reads it.
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token. OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp).
The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user.
Not yet documented: how to obtain a token.
Not yet documented: token lifetime.
Body
Unit: minutes
Refers to TimeRegistrationRead.TimeRegistrationID. Look up valid values with GET /v1/time-registration/{timeRegistrationID}.
- Always (POST /v1/time-tracker) — The default adapter branch never reads it.
Responses
A time tracker (stopwatch) of one employee. A tracker is either running (TimeTrackerStatus 1) or ended but not yet turned into a time registration (TimeTrackerStatus 2). When a tracker is stopped and its data forms a valid registration, the registration is written and the tracker row is deleted, so a tracker is short-lived.