Start a time tracker on an absence code
Starts a stopwatch for the calling user on an absence code.
Creates a running, non-billable time tracker for the authenticated user on AbsenceCodeID, starting now (server clock). Any running tracker of the caller is stopped first and converted into a time registration. With TimeRegistrationID, comment, additional text, factor and monthly period are copied from that registration and the tracker is linked to it when it is dated today; the absence code always comes from AbsenceCodeID. Returns the new tracker.
Behaviour:
- Not idempotent.
- Not safe to retry blindly.
- Side effect: Stops the caller's running tracker (if any) and converts it into time registration(s).
- Side effect: Creates the tracker (TimeTrackerCreated event); notifies invoicing potential.
- Changes are visible to the next read immediately.
Next: POST /v1/time-registration/stop-time-tracker/{timeTrackerId}, GET /v1/time-tracker/active-time-tracker
Not yet documented: behaviour (linked project registration); examples (success).
curl -X POST "https://app3.timelog.com/your-account/api/v1/time-tracker/absence/start-time-tracker" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"AbsenceCodeID": 123,
"TimeRegistrationID": "null",
"Minute": 42,
"Comment": "null"
}'
import requests
import json
url = "https://app3.timelog.com/your-account/api/v1/time-tracker/absence/start-time-tracker"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"AbsenceCodeID": 123,
"TimeRegistrationID": "null",
"Minute": 42,
"Comment": "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/absence/start-time-tracker", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
"AbsenceCodeID": 123,
"TimeRegistrationID": "null",
"Minute": 42,
"Comment": "null"
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"AbsenceCodeID": 123,
"TimeRegistrationID": "null",
"Minute": 42,
"Comment": "null"
}`)
req, err := http.NewRequest("POST", "https://app3.timelog.com/your-account/api/v1/time-tracker/absence/start-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/absence/start-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 = '{
"AbsenceCodeID": 123,
"TimeRegistrationID": "null",
"Minute": 42,
"Comment": "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/absence/start-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
The absence code to track. Always used, also when TimeRegistrationID is sent (it replaces the registration's entity).
Refers to AbsenceCodeRead.AbsenceCodeID.
Start from an existing registration: copies comment, additional text, factor and monthly period, and LINKS the tracker when the registration is dated today (server date).
Refers to TimeRegistrationRead.TimeRegistrationID. Look up valid values with GET /v1/time-registration/{timeRegistrationID}.
Minutes already counted before now. With TimeRegistrationID and a value > 0: the expected total. Unit: minutes
- Always — Overwrites the tracker comment, including the registration's comment when TimeRegistrationID is sent and Comment is omitted.
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
The absence code to track. Always used, also when TimeRegistrationID is sent (it replaces the registration's entity).
Refers to AbsenceCodeRead.AbsenceCodeID.
Start from an existing registration: copies comment, additional text, factor and monthly period, and LINKS the tracker when the registration is dated today (server date).
Refers to TimeRegistrationRead.TimeRegistrationID. Look up valid values with GET /v1/time-registration/{timeRegistrationID}.
Minutes already counted before now. With TimeRegistrationID and a value > 0: the expected total.
Unit: minutes
- Always — Overwrites the tracker comment, including the registration's comment when TimeRegistrationID is sent and Comment is omitted.
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.