Time-off
GET Get time offs of organization users
https://focus.toggl.com/api/organizations/{organization_id}/timeoff
Returns the time off of the given organization users with personal detail stripped: each entry carries only its id, the user it belongs to, and the start and end of the period — no category and no audit timestamps. Available to any member of the organization. user_id is required and repeatable, and so is the start_date/end_date window; both are dates (YYYY-MM-DD), interpreted in UTC, and end_date is inclusive of that whole day. An entry is returned when its period overlaps the window at either edge, so an entry that starts before start_date or ends after end_date is still included.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/timeoff \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/timeoff")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/timeoff')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/timeoff", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/timeoff', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/timeoff".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|---|---|---|
| organization_id | integer | true | Organization ID |
Query
| name | type | required | description |
|---|---|---|---|
| user_id | []integer | true | User IDs |
| start_date | string | true | From date (YYYY-MM-DD) |
| end_date | string | true | To date (YYYY-MM-DD) |
Response
200
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| end_time | string | EndTime is the RFC3339 timestamp (UTC) the time off period ends at; always after StartTime. |
| start_time | string | StartTime is the RFC3339 timestamp (UTC) the time off period starts at. |
| timeoff_id | integer | ID is the unique identifier of the time off entry. |
| user_id | integer | UserID is the user the time off was booked for. |
400
Invalid parameters
403
Forbidden
500
Internal Server Error
GET Get time off for organization user
https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}
Returns the full time off entries of one organization user, including the category and the creation and last-modification timestamps. Requires the manage_time_off organization permission — this applies to reading as well, and to a caller's own entries. The from/to window is required; both are dates (YYYY-MM-DD), interpreted in UTC, and to is inclusive of that whole day. An entry is returned when its period overlaps the window at either edge, so an entry that starts before from or ends after to is still included.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id} \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|---|---|---|
| organization_id | integer | true | Organization ID |
| user_id | integer | true | User ID |
Query
| name | type | required | description |
|---|---|---|---|
| from | string | true | From date (YYYY-MM-DD) |
| to | string | true | To date (YYYY-MM-DD) |
Response
200
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| created_at | string | CreatedAt is the RFC3339 timestamp (UTC) the entry was created at. |
| end_time | string | EndTime is the RFC3339 timestamp (UTC) the time off period ends at; always after StartTime. |
| organization_id | integer | OrganizationID is the organization the entry belongs to. |
| start_time | string | StartTime is the RFC3339 timestamp (UTC) the time off period starts at. |
| timeoff_id | integer | ID is the unique identifier of the time off entry. |
| type | string | Type is the category of the time off: vacation, sick, parental or other. Omitted when the entry has no category. |
| updated_at | string | UpdatedAt is the RFC3339 timestamp (UTC) the entry was last modified at. |
| user_id | integer | UserID is the user the time off was booked for. |
400
Invalid parameters
403
Forbidden
500
Internal Server Error
PUT Update time off for the specified user
https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}
Updates one or more existing time off entries of the specified user in a single call. The request body is an array: each element identifies the entry by its timeoff_id and carries the new start_time and end_time (RFC3339) plus an optional type. Every element replaces the entry in full, so omitting type clears the entry's existing category rather than leaving it unchanged — resend the current value to keep it. Include each timeoff_id at most once: with duplicates, which element wins is undefined. Elements whose timeoff_id does not match an entry of the user are skipped. All elements are applied in a single transaction: if applying them would leave any two of the user's approved or pending time off entries overlapping (entries created through this API are approved), the whole request fails with a 409 and nothing is updated. Requires the manage_time_off organization permission. Responds 200 with the entries that were actually updated.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PUT https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id} \
-H "Content-Type: application/json" \
-d '[\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}]' \
-u <email>:<password>
bytes, err := json.Marshal('[\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}]')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}')
req = Net::HTTP::Put.new(uri)
req['Content-Type'] = "application/json"
req.body = [\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}].to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", {
method: "PUT",
body: [\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}],
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.put('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}', json=[\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}], headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PUT, "https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}".to_string())
.json(&serde_json::json!([\{"end_time":"string","start_time":"string","timeoff_id":"integer","type":"string"\}]))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|---|---|---|
| organization_id | integer | true | Organization ID |
| user_id | integer | true | User ID |
Body
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| end_time | string | EndTime is the RFC3339 timestamp the time off period ends at; must be after StartTime. Send it in UTC: offsets are discarded, not converted. |
| start_time | string | StartTime is the RFC3339 timestamp the time off period starts at. Send it in UTC: offsets are discarded, not converted. |
| timeoff_id | integer | ID is the unique identifier of the time off entry to update. |
| type | string | Type is the optional category of the time off: vacation, sick, parental or other. Omitting it clears the entry's stored category. Valid values: vacation, sick, parental, other. |
Response
200
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| created_at | string | CreatedAt is the RFC3339 timestamp (UTC) the entry was created at. |
| end_time | string | EndTime is the RFC3339 timestamp (UTC) the time off period ends at; always after StartTime. |
| organization_id | integer | OrganizationID is the organization the entry belongs to. |
| start_time | string | StartTime is the RFC3339 timestamp (UTC) the time off period starts at. |
| timeoff_id | integer | ID is the unique identifier of the time off entry. |
| type | string | Type is the category of the time off: vacation, sick, parental or other. Omitted when the entry has no category. |
| updated_at | string | UpdatedAt is the RFC3339 timestamp (UTC) the entry was last modified at. |
| user_id | integer | UserID is the user the time off was booked for. |
400
Invalid parameters
403
Forbidden
409
Overlapping time off entry
500
Internal Server Error
POST Create time off for the specified user
https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}
Creates one or more time off entries for the specified user in a single call. The request body is an array: each element needs a start_time and an end_time (RFC3339) and may carry an optional type. All elements are created in a single transaction: a period that overlaps one of the user's approved or pending time off entries — or another element of the same request — fails the whole request with a 409 and nothing is created (entries created through this API are approved). Requires the manage_time_off organization permission. Responds 200 with the created entries, each including the id it was assigned.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X POST https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id} \
-H "Content-Type: application/json" \
-d '[\{"end_time":"string","start_time":"string","type":"string"\}]' \
-u <email>:<password>
bytes, err := json.Marshal('[\{"end_time":"string","start_time":"string","type":"string"\}]')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPost,
"https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = "application/json"
req.body = [\{"end_time":"string","start_time":"string","type":"string"\}].to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", {
method: "POST",
body: [\{"end_time":"string","start_time":"string","type":"string"\}],
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.post('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}', json=[\{"end_time":"string","start_time":"string","type":"string"\}], headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::POST, "https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}".to_string())
.json(&serde_json::json!([\{"end_time":"string","start_time":"string","type":"string"\}]))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|---|---|---|
| organization_id | integer | true | Organization ID |
| user_id | integer | true | User ID |
Body
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| end_time | string | EndTime is the RFC3339 timestamp the time off period ends at; must be after StartTime. Send it in UTC: offsets are discarded, not converted. |
| start_time | string | StartTime is the RFC3339 timestamp the time off period starts at. Send it in UTC: offsets are discarded, not converted. |
| type | string | Type is the optional category of the time off: vacation, sick, parental or other. Omit to leave the entry uncategorized. Valid values: vacation, sick, parental, other. |
Response
200
| Name | Type | Description |
|---|---|---|
| items | Array of object | - |
items
| Name | Type | Description |
|---|---|---|
| created_at | string | CreatedAt is the RFC3339 timestamp (UTC) the entry was created at. |
| end_time | string | EndTime is the RFC3339 timestamp (UTC) the time off period ends at; always after StartTime. |
| organization_id | integer | OrganizationID is the organization the entry belongs to. |
| start_time | string | StartTime is the RFC3339 timestamp (UTC) the time off period starts at. |
| timeoff_id | integer | ID is the unique identifier of the time off entry. |
| type | string | Type is the category of the time off: vacation, sick, parental or other. Omitted when the entry has no category. |
| updated_at | string | UpdatedAt is the RFC3339 timestamp (UTC) the entry was last modified at. |
| user_id | integer | UserID is the user the time off was booked for. |
400
Invalid parameters
403
Forbidden
409
Overlapping time off entry
500
Internal Server Error
DELETE Delete time off for the specified user
https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}
Deletes one or more time off entries of the specified user. The request body is an array of time off ids. Ids that do not match an entry of the user are skipped silently — the response does not indicate how many entries were deleted. Requires the manage_time_off organization permission. Responds 204 with no body.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X DELETE https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id} \
-H "Content-Type: application/json" \
-d '[\{\}]' \
-u <email>:<password>
bytes, err := json.Marshal('[\{\}]')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}')
req = Net::HTTP::Delete.new(uri)
req['Content-Type'] = "application/json"
req.body = [\{\}].to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}", {
method: "DELETE",
body: [\{\}],
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.delete('https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}', json=[\{\}], headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::DELETE, "https://focus.toggl.com/api/organizations/{organization_id}/timeoff/users/{user_id}".to_string())
.json(&serde_json::json!([\{\}]))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|---|---|---|
| organization_id | integer | true | Organization ID |
| user_id | integer | true | User ID |
Body
| Name | Type | Description |
|---|---|---|
| items | Array of integer | - |
Response
204
No Content
400
Invalid parameters
403
Forbidden
500
Internal Server Error