Get the suggested rate for allocating a user to a task
For a user not yet allocated to a task, returns the contract hourly rate TimeLog would assign and whether a rate can be chosen.
Returns at most ONE entity: when userId is an active user without an allocation on taskId (and not an inactive member of the project's resource group) and the task is neither Completed nor Cancelled, the rate TimeLog resolves for that employee on the task (task rate → contract team member → resource group → project standard rate → employee's standard rate by service → the contract's first rate), with its amount, the PATH project's currency abbreviation and IsShownHourlyRateDropDown. Otherwise an empty list.
Use it to:
- Pre-fill the hourly rate when allocating a person to a task
Not for:
- The rates a contract offers →
GET /v2/contract-hourly-rates/dropdown-content
Behaviour:
- Idempotent.
- Same answer on repeat; but the first call may create a contract hourly rate; later calls find it.
- Safe to retry.
- Side effect: May CREATE a Project-type contract hourly rate on the task's contract (employee's standard rate, service missing on the contract) and notify its creation.
- Changes are visible to the next read immediately.
Call first: GET /v1/user, GET /v1/task
Next: POST /v1/task/{taskID}/allocation
See also: GET /v2/projects/{projectId}/employee-allocation, GET /v2/contract-hourly-rates/dropdown-content
Not yet documented: examples.
curl -X GET "https://app3.timelog.com/your-account/api/v2/projects/123/employee-unallocated?taskId=123&userId=123" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN"
import requests
import json
url = "https://app3.timelog.com/your-account/api/v2/projects/123/employee-unallocated?taskId=123&userId=123"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
response = requests.get(url, headers=headers)
print(response.json())
const response = await fetch("https://app3.timelog.com/your-account/api/v2/projects/123/employee-unallocated?taskId=123&userId=123", {
method: "GET",
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("GET", "https://app3.timelog.com/your-account/api/v2/projects/123/employee-unallocated?taskId=123&userId=123", 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/projects/123/employee-unallocated?taskId=123&userId=123')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
response = http.request(request)
puts response.body
{
"Entities": [
{
"Properties": {
"UserId": 123,
"SuggestedHourlyRateId": 123,
"SuggestedHourlyRateName": "null",
"SuggestedHourlyRateAmount": 3.14,
"HourlyRateCurrencyAbb": "example_string",
"IsShownHourlyRateDropDown": true
},
"Links": [
{
"Href": "example_string",
"Rel": "example_string"
}
],
"Actions": [
{}
]
}
],
"Links": [
{
"Href": "example_string",
"Rel": "example_string"
}
]
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Not Found",
"message": "The requested resource was not found",
"code": 404
}
{
"error": "Internal Server Error",
"message": "An unexpected error occurred on the server",
"code": 500,
"requestId": "req_1234567890"
}
/v2/projects/{projectId}/employee-unallocatedTarget 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.Project whose currency abbreviation is returned. Not checked against taskId. Unknown → 500.
The task. Omitted → 404 (captured); unknown → 500.
The user. Unknown, inactive or already allocated → empty list.
Filters on UnallocatedEmployeeRead.UserId (eq).
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.
Path Parameters
Project whose currency abbreviation is returned. Not checked against taskId. Unknown → 500.
Query Parameters
The task. Omitted → 404 (captured); unknown → 500.
The user. Unknown, inactive or already allocated → empty list.
Filters on UnallocatedEmployeeRead.UserId (eq).
Responses
Omitted (not []) when the list is empty.