Complete or reopen a milestone
Marks a milestone (or one occurrence of a recurring milestone) as completed or not completed.
Send the MilestoneId and IsRecurring of a GET /v2/milestones/incomplete entity unchanged. isRecurring=true treats id as a recurring-milestone INSTANCE ID and flips only that occurrence's IsCompleted (no event); isRecurring=false treats id as a milestone ID, sets its completion, refreshes the parent task's status, saves it with the caller as modifier and raises MilestoneChangeStatus. Setting the status it already has does nothing. Answers 200 with body null. The flag is trusted: a wrong isRecurring addresses a different milestone that shares the number.
Use it to:
- Tick off a milestone from a reminder list
Behaviour:
- Idempotent.
- Safe to retry.
- Side effect: Recurring instance: IsCompleted, LastModifiedBy, LastModified updated (no event).
- Changes are visible to the next read immediately.
Call first: GET /v2/milestones/incomplete
curl -X PUT "https://app3.timelog.com/your-account/api/v2/milestones/123/status?isCompleted=true&isRecurring=true" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN"
import requests
import json
url = "https://app3.timelog.com/your-account/api/v2/milestones/123/status?isCompleted=true&isRecurring=true"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
response = requests.put(url, headers=headers)
print(response.json())
const response = await fetch("https://app3.timelog.com/your-account/api/v2/milestones/123/status?isCompleted=true&isRecurring=true", {
method: "PUT",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("PUT", "https://app3.timelog.com/your-account/api/v2/milestones/123/status?isCompleted=true&isRecurring=true", nil)
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/v2/milestones/123/status?isCompleted=true&isRecurring=true')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Put.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
response = http.request(request)
puts response.body
"null"
{
"Message": "Authorization has been denied for this request."
}
{
"Message": "No HTTP resource was found that matches the request URI 'https://app{server-number}.timelog.com/{account}/api/v2/milestones/{id}/status'.",
"MessageDetail": "No action was found on the controller '…' that matches the request."
}
{
"Code": 100,
"Message": "Unknown error occur in system, please contact system administrator.",
"Details": [],
"Parameters": "…",
"Url": "https://app{server-number}.timelog.com/{account}/api/v2/milestones/{id}/status"
}
/v2/milestones/{id}/statusTarget 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.
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.MilestoneId from the list: a recurring-instance ID when isRecurring is true, otherwise a milestone ID. Unknown → 500.
true = completed, false = reopen. Omitted → 404 (captured).
Which ID space id belongs to — pass MilestoneRead.IsRecurring unchanged. Omitted → 404 (captured).
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.
Path Parameters
MilestoneId from the list: a recurring-instance ID when isRecurring is true, otherwise a milestone ID. Unknown → 500.
Query Parameters
true = completed, false = reopen. Omitted → 404 (captured).
Which ID space id belongs to — pass MilestoneRead.IsRecurring unchanged. Omitted → 404 (captured).
Responses
*Success without content: HTTP 200 with the literal JSON body null. Body is the JSON literal null (TafSuccessResult), also when nothing changed.
Empty result: Not applicable.*