curl --request PATCH \
--url https://api.threadi.au/stopwatch/v1/timelogs/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"properties": {
"a552213_assoc_obj_type": "contact",
"a552213_assoc_record_id": "123456789",
"a552213_description": "Updated via StopWatch API"
}
}
'import requests
url = "https://api.threadi.au/stopwatch/v1/timelogs/{id}"
payload = { "properties": {
"a552213_assoc_obj_type": "contact",
"a552213_assoc_record_id": "123456789",
"a552213_description": "Updated via StopWatch API"
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
properties: {
a552213_assoc_obj_type: 'contact',
a552213_assoc_record_id: '123456789',
a552213_description: 'Updated via StopWatch API'
}
})
};
fetch('https://api.threadi.au/stopwatch/v1/timelogs/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.threadi.au/stopwatch/v1/timelogs/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'properties' => [
'a552213_assoc_obj_type' => 'contact',
'a552213_assoc_record_id' => '123456789',
'a552213_description' => 'Updated via StopWatch API'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.threadi.au/stopwatch/v1/timelogs/{id}"
payload := strings.NewReader("{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.threadi.au/stopwatch/v1/timelogs/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.threadi.au/stopwatch/v1/timelogs/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": 1234567890,
"properties": {
"a552213_record_id": "998877 -- 2026-03-20 04:22:15.536",
"a552213_toggle": true,
"a552213_assoc_record_id": 9876543210,
"a552213_first_start_date": "2026-02-27T21:24:18.038Z",
"a552213_first_end_date": "2026-02-28T21:24:18.038Z",
"a552213_last_start_date": "2026-02-27T21:24:18.038Z",
"a552213_last_end_date": "2026-02-28T21:24:18.038Z",
"a552213_total_minutes": 1440,
"a552213_total_hours": 24,
"a552213_total_days": 1,
"a552213_total_years": 0.00273785,
"a552213_total_decades": 0.00027379,
"a552213_total_centuries": 0.00002738,
"a552213_num_sessions": 1,
"a552213_week_year": "2026-02-23T00:00:00.000Z",
"a552213_month_year": "2026-02-01T00:00:00.000Z",
"a552213_is_split_week_record": true,
"a552213_is_split_month_record": true,
"a552213_workflow_managed_tag": "example_tag",
"a552213_billable_minutes": 0,
"a552213_billable_hours": 0,
"a552213_billable_days": 0,
"a552213_billable_years": 0,
"a552213_billable_decades": 0,
"a552213_billable_centuries": 0,
"a552213_billable_amount": 0,
"a552213_cost_amount": 0,
"a552213_margin_amount": 0,
"a552213_is_one_time_log_per_session_record": true,
"a552213_category_text": "Meetings",
"a552213_description": "Meeting about Project XYZ",
"a552213_billable_percentage": 0,
"a552213_service_name": "Training",
"a552213_total_hours_auto": 0,
"a552213_total_days_auto": 0,
"a552213_total_years_auto": 0,
"a552213_total_decades_auto": 0,
"a552213_total_centuries_auto": 0,
"a552213_billable_hours_auto": 0,
"a552213_billable_days_auto": 0,
"a552213_billable_years_auto": 0,
"a552213_billable_decades_auto": 0,
"a552213_billable_centuries_auto": 0,
"a552213_billable_rate": 0,
"a552213_cost_rate": 0,
"a552213_billable_amount_auto": 0,
"a552213_cost_amount_auto": 0,
"a552213_margin_amount_auto": 0,
"a552213_title": "Training Session X",
"a552213_created_via_stopwatch_api": "true",
"a552213_last_updated_via_stopwatch_api": "1784160000000"
},
"createdAt": "2026-02-27T21:24:18.038Z",
"updatedAt": "2026-02-28T21:24:18.038Z",
"archived": true,
"association": {
"attempted": true,
"status": "success",
"reason": "Both association properties were not supplied",
"fromObjectType": "a552213_TIME_LOG",
"fromRecordId": "151993156822",
"toObjectType": "contacts",
"toRecordId": "123456789",
"statusCode": 200,
"error": "<hubspot association error as string>"
}
}{
"id": 1234567890,
"properties": {
"a552213_record_id": "998877 -- 2026-03-20 04:22:15.536",
"a552213_toggle": true,
"a552213_assoc_record_id": 9876543210,
"a552213_first_start_date": "2026-02-27T21:24:18.038Z",
"a552213_first_end_date": "2026-02-28T21:24:18.038Z",
"a552213_last_start_date": "2026-02-27T21:24:18.038Z",
"a552213_last_end_date": "2026-02-28T21:24:18.038Z",
"a552213_total_minutes": 1440,
"a552213_total_hours": 24,
"a552213_total_days": 1,
"a552213_total_years": 0.00273785,
"a552213_total_decades": 0.00027379,
"a552213_total_centuries": 0.00002738,
"a552213_num_sessions": 1,
"a552213_week_year": "2026-02-23T00:00:00.000Z",
"a552213_month_year": "2026-02-01T00:00:00.000Z",
"a552213_is_split_week_record": true,
"a552213_is_split_month_record": true,
"a552213_workflow_managed_tag": "example_tag",
"a552213_billable_minutes": 0,
"a552213_billable_hours": 0,
"a552213_billable_days": 0,
"a552213_billable_years": 0,
"a552213_billable_decades": 0,
"a552213_billable_centuries": 0,
"a552213_billable_amount": 0,
"a552213_cost_amount": 0,
"a552213_margin_amount": 0,
"a552213_is_one_time_log_per_session_record": true,
"a552213_category_text": "Meetings",
"a552213_description": "Meeting about Project XYZ",
"a552213_billable_percentage": 0,
"a552213_service_name": "Training",
"a552213_total_hours_auto": 0,
"a552213_total_days_auto": 0,
"a552213_total_years_auto": 0,
"a552213_total_decades_auto": 0,
"a552213_total_centuries_auto": 0,
"a552213_billable_hours_auto": 0,
"a552213_billable_days_auto": 0,
"a552213_billable_years_auto": 0,
"a552213_billable_decades_auto": 0,
"a552213_billable_centuries_auto": 0,
"a552213_billable_rate": 0,
"a552213_cost_rate": 0,
"a552213_billable_amount_auto": 0,
"a552213_cost_amount_auto": 0,
"a552213_margin_amount_auto": 0,
"a552213_title": "Training Session X",
"a552213_created_via_stopwatch_api": "true",
"a552213_last_updated_via_stopwatch_api": "1784160000000"
},
"createdAt": "2026-02-27T21:24:18.038Z",
"updatedAt": "2026-02-28T21:24:18.038Z",
"archived": true,
"association": {
"attempted": true,
"status": "success",
"reason": "Both association properties were not supplied",
"fromObjectType": "a552213_TIME_LOG",
"fromRecordId": "151993156822",
"toObjectType": "contacts",
"toRecordId": "123456789",
"statusCode": 200,
"error": "<hubspot association error as string>"
}
}{
"error": "HubSpot API Error",
"details": "<hubspot error as string>"
}{
"error": "Invalid API key"
}{
"error": "API key has been deactivated"
}{
"error": "HubSpot API Error",
"details": "<html>\\n<head>\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html;charset=utf-8\\\"/>\\n<title>Error 404 Not Found</title>\\n</head>\\n<body><h2>HTTP ERROR 404</h2>\\n<p>Resource not found</p>\\n</body>\\n</html>\\n\n"
}{
"error": "Daily quota exceeded",
"details": "This API key has reached its UTC daily request limit. Use response header x-stopwatch-ratelimit-reset to know when this quota will reset."
}{
"error": "Internal Server Error",
"details": "An unexpected error occurred."
}{
"error": "Service temporarily busy",
"details": "Unable to process request right now. Please retry shortly."
}Update Time Log
Updates a StopWatch Time Log record by ID.
See HubSpot API documentation for the list of valid Query Parameters.
curl --request PATCH \
--url https://api.threadi.au/stopwatch/v1/timelogs/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"properties": {
"a552213_assoc_obj_type": "contact",
"a552213_assoc_record_id": "123456789",
"a552213_description": "Updated via StopWatch API"
}
}
'import requests
url = "https://api.threadi.au/stopwatch/v1/timelogs/{id}"
payload = { "properties": {
"a552213_assoc_obj_type": "contact",
"a552213_assoc_record_id": "123456789",
"a552213_description": "Updated via StopWatch API"
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
properties: {
a552213_assoc_obj_type: 'contact',
a552213_assoc_record_id: '123456789',
a552213_description: 'Updated via StopWatch API'
}
})
};
fetch('https://api.threadi.au/stopwatch/v1/timelogs/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.threadi.au/stopwatch/v1/timelogs/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'properties' => [
'a552213_assoc_obj_type' => 'contact',
'a552213_assoc_record_id' => '123456789',
'a552213_description' => 'Updated via StopWatch API'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.threadi.au/stopwatch/v1/timelogs/{id}"
payload := strings.NewReader("{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.threadi.au/stopwatch/v1/timelogs/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.threadi.au/stopwatch/v1/timelogs/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"properties\": {\n \"a552213_assoc_obj_type\": \"contact\",\n \"a552213_assoc_record_id\": \"123456789\",\n \"a552213_description\": \"Updated via StopWatch API\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": 1234567890,
"properties": {
"a552213_record_id": "998877 -- 2026-03-20 04:22:15.536",
"a552213_toggle": true,
"a552213_assoc_record_id": 9876543210,
"a552213_first_start_date": "2026-02-27T21:24:18.038Z",
"a552213_first_end_date": "2026-02-28T21:24:18.038Z",
"a552213_last_start_date": "2026-02-27T21:24:18.038Z",
"a552213_last_end_date": "2026-02-28T21:24:18.038Z",
"a552213_total_minutes": 1440,
"a552213_total_hours": 24,
"a552213_total_days": 1,
"a552213_total_years": 0.00273785,
"a552213_total_decades": 0.00027379,
"a552213_total_centuries": 0.00002738,
"a552213_num_sessions": 1,
"a552213_week_year": "2026-02-23T00:00:00.000Z",
"a552213_month_year": "2026-02-01T00:00:00.000Z",
"a552213_is_split_week_record": true,
"a552213_is_split_month_record": true,
"a552213_workflow_managed_tag": "example_tag",
"a552213_billable_minutes": 0,
"a552213_billable_hours": 0,
"a552213_billable_days": 0,
"a552213_billable_years": 0,
"a552213_billable_decades": 0,
"a552213_billable_centuries": 0,
"a552213_billable_amount": 0,
"a552213_cost_amount": 0,
"a552213_margin_amount": 0,
"a552213_is_one_time_log_per_session_record": true,
"a552213_category_text": "Meetings",
"a552213_description": "Meeting about Project XYZ",
"a552213_billable_percentage": 0,
"a552213_service_name": "Training",
"a552213_total_hours_auto": 0,
"a552213_total_days_auto": 0,
"a552213_total_years_auto": 0,
"a552213_total_decades_auto": 0,
"a552213_total_centuries_auto": 0,
"a552213_billable_hours_auto": 0,
"a552213_billable_days_auto": 0,
"a552213_billable_years_auto": 0,
"a552213_billable_decades_auto": 0,
"a552213_billable_centuries_auto": 0,
"a552213_billable_rate": 0,
"a552213_cost_rate": 0,
"a552213_billable_amount_auto": 0,
"a552213_cost_amount_auto": 0,
"a552213_margin_amount_auto": 0,
"a552213_title": "Training Session X",
"a552213_created_via_stopwatch_api": "true",
"a552213_last_updated_via_stopwatch_api": "1784160000000"
},
"createdAt": "2026-02-27T21:24:18.038Z",
"updatedAt": "2026-02-28T21:24:18.038Z",
"archived": true,
"association": {
"attempted": true,
"status": "success",
"reason": "Both association properties were not supplied",
"fromObjectType": "a552213_TIME_LOG",
"fromRecordId": "151993156822",
"toObjectType": "contacts",
"toRecordId": "123456789",
"statusCode": 200,
"error": "<hubspot association error as string>"
}
}{
"id": 1234567890,
"properties": {
"a552213_record_id": "998877 -- 2026-03-20 04:22:15.536",
"a552213_toggle": true,
"a552213_assoc_record_id": 9876543210,
"a552213_first_start_date": "2026-02-27T21:24:18.038Z",
"a552213_first_end_date": "2026-02-28T21:24:18.038Z",
"a552213_last_start_date": "2026-02-27T21:24:18.038Z",
"a552213_last_end_date": "2026-02-28T21:24:18.038Z",
"a552213_total_minutes": 1440,
"a552213_total_hours": 24,
"a552213_total_days": 1,
"a552213_total_years": 0.00273785,
"a552213_total_decades": 0.00027379,
"a552213_total_centuries": 0.00002738,
"a552213_num_sessions": 1,
"a552213_week_year": "2026-02-23T00:00:00.000Z",
"a552213_month_year": "2026-02-01T00:00:00.000Z",
"a552213_is_split_week_record": true,
"a552213_is_split_month_record": true,
"a552213_workflow_managed_tag": "example_tag",
"a552213_billable_minutes": 0,
"a552213_billable_hours": 0,
"a552213_billable_days": 0,
"a552213_billable_years": 0,
"a552213_billable_decades": 0,
"a552213_billable_centuries": 0,
"a552213_billable_amount": 0,
"a552213_cost_amount": 0,
"a552213_margin_amount": 0,
"a552213_is_one_time_log_per_session_record": true,
"a552213_category_text": "Meetings",
"a552213_description": "Meeting about Project XYZ",
"a552213_billable_percentage": 0,
"a552213_service_name": "Training",
"a552213_total_hours_auto": 0,
"a552213_total_days_auto": 0,
"a552213_total_years_auto": 0,
"a552213_total_decades_auto": 0,
"a552213_total_centuries_auto": 0,
"a552213_billable_hours_auto": 0,
"a552213_billable_days_auto": 0,
"a552213_billable_years_auto": 0,
"a552213_billable_decades_auto": 0,
"a552213_billable_centuries_auto": 0,
"a552213_billable_rate": 0,
"a552213_cost_rate": 0,
"a552213_billable_amount_auto": 0,
"a552213_cost_amount_auto": 0,
"a552213_margin_amount_auto": 0,
"a552213_title": "Training Session X",
"a552213_created_via_stopwatch_api": "true",
"a552213_last_updated_via_stopwatch_api": "1784160000000"
},
"createdAt": "2026-02-27T21:24:18.038Z",
"updatedAt": "2026-02-28T21:24:18.038Z",
"archived": true,
"association": {
"attempted": true,
"status": "success",
"reason": "Both association properties were not supplied",
"fromObjectType": "a552213_TIME_LOG",
"fromRecordId": "151993156822",
"toObjectType": "contacts",
"toRecordId": "123456789",
"statusCode": 200,
"error": "<hubspot association error as string>"
}
}{
"error": "HubSpot API Error",
"details": "<hubspot error as string>"
}{
"error": "Invalid API key"
}{
"error": "API key has been deactivated"
}{
"error": "HubSpot API Error",
"details": "<html>\\n<head>\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html;charset=utf-8\\\"/>\\n<title>Error 404 Not Found</title>\\n</head>\\n<body><h2>HTTP ERROR 404</h2>\\n<p>Resource not found</p>\\n</body>\\n</html>\\n\n"
}{
"error": "Daily quota exceeded",
"details": "This API key has reached its UTC daily request limit. Use response header x-stopwatch-ratelimit-reset to know when this quota will reset."
}{
"error": "Internal Server Error",
"details": "An unexpected error occurred."
}{
"error": "Service temporarily busy",
"details": "Unable to process request right now. Please retry shortly."
}Authorizations
Bearer Authorization header of the form Bearer {token}, where {token} is your API key. By default, each API key is rate-limited to 1,000 requests per day (UTC). If you need a higher daily limit, please submit a support request.
Path Parameters
The ID of the StopWatch Time Log record. By default, this is the HubSpot hs_object_id. If you want to update a Time Log by its unique StopWatch Record Id, you can use the idProperty query parameter to specify a552213_record_id instead.
Body
Properties must use exact, whole HubSpot property internal names. Retrieve valid property names from the List Properties endpoint. Required properties cannot be unset or cleared. Calculated and app-managed properties cannot be updated.
Show child attributes
Show child attributes

