TimeOff Requests
A time off request is an employee's ask to take time off under a specific Time Off Request Type. A request starts out Pending and moves to Approved or Denied when an admin resolves it. Approving or denying a request doesn't itself deduct from an employee's accrued balance — see Time Off Policies for how balances and accrual work.
Auth
Requires a bearer access token (see How to Get API Access). Approving or denying a request requires an Admin-level token.
Endpoints overview
| Method | Name | Endpoint |
|---|---|---|
| POST | Create Time Off Request | https://api.worklio.com/wep/companies/{CLIENT_ID}/timeoff-requests |
| PUT | Approve Time Off Request | https://api.worklio.com/wep/companies/{CLIENT_ID}/approved-timeoff-requests/{REQUEST_ID} |
| PUT | Deny Time Off Request | https://api.worklio.com/wep/companies/{CLIENT_ID}/denied-timeoff-requests/{REQUEST_ID} |
CLIENT_ID is the company identifier returned as id when you create the company. REQUEST_ID is the request identifier returned as id when you create a time off request (below).
Create Time Off Request
POST https://api.worklio.com/wep/companies/{CLIENT_ID}/timeoff-requests
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
employeeId | integer | Yes | The employee this request is for. |
typeId | integer | Yes | The time off request type this request is filed under. |
startOn | object | Yes | Start of the requested time off. See startOn/endOn object below. |
duration | integer (minutes) | Yes | Length of the request, in minutes. |
reason | string | No | Optional note from the employee explaining the request. |
startOn / endOn object
startOn / endOn object| Field | Type | Description |
|---|---|---|
item | string | A date ("2026-09-16") or an ISO 8601 datetime. |
withoutTime | boolean | Whether item is a date only, with no specific time of day. |
endOn isn't sent on create — it's computed by the server from startOn plus duration and returned in the response.
withoutTimeisn't preserved as sent. Even if you sendstartOn.itemas a bare date withwithoutTime: true, the response echoes back a resolved UTC datetime withwithoutTime: false. Don't rely onwithoutTimestayingtruein the stored object.
Example request
require("dotenv").config();
const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const TIMEOFF_TYPE_ID = process.env.TIMEOFF_TYPE_ID;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/timeoff-requests`;
const payload = {
employeeId: process.env.EMPLOYEE_ID,
typeId: TIMEOFF_TYPE_ID,
startOn: {
item: "2026-09-16",
withoutTime: true
},
duration: 300
};
async function createTimeOffRequest() {
const response = await fetch(url, {
method: "POST",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"content-type": "application/json",
"x-api-version": "2.0"
},
body: JSON.stringify(payload)
});
console.log(response.status);
console.log(await response.text());
}
createTimeOffRequest();curl -s -X POST "https://api.worklio.com/wep/companies/$CLIENT_ID/timeoff-requests" \
-H "accept: application/json" \
-H "api-version: 2.0" \
-H "authorization: Bearer $API_KEY" \
-H "content-type: application/json" \
-H "x-api-version: 2.0" \
-d '{
"employeeId": "'"$EMPLOYEE_ID"'",
"typeId": "'"$TIMEOFF_TYPE_ID"'",
"startOn": {
"item": "2026-09-16",
"withoutTime": true
},
"duration": 300
}' | jq .Example response
{
"id": 28,
"requestedOn": "2026-09-17T14:37:49Z",
"status": 1,
"employeeId": 4308,
"workLocationId": 1266,
"typeId": 7,
"payCodeType": 1,
"startOn": {
"item": "2026-09-16T05:00:00Z",
"withoutTime": false
},
"endOn": {
"item": "2026-09-16T10:00:00Z",
"withoutTime": false
},
"duration": 300,
"reason": "",
"note": "",
"usedDuration": 0
}Response fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique identifier for the request. This is the REQUEST_ID used to approve or deny it. |
requestedOn | string (datetime) | When the request was submitted. |
status | integer (enum) | See Status values below. |
employeeId | integer | The employee the request is for. |
workLocationId | integer | The employee's work location. Set automatically from the employee record. |
typeId | integer | The time off request type this request was filed under. |
payCodeType | integer (enum) | Pay code category, set automatically from typeId. See Pay Code Type values in Time Off Request Types. |
startOn / endOn | object | Start and end of the requested time off. endOn is computed from startOn + duration. |
duration | integer (minutes) | Length of the request. |
reason | string | The employee's reason for the request, if one was given on create. |
note | string | Set when the request is approved or denied — see below. Empty until then. |
usedDuration | integer (minutes) | How much of this request's duration has been used so far. |
resolvedBy | object | Present only after the request has been approved or denied. See Approve/Deny below. |
resolvedOn | string (datetime) | Present only after the request has been approved or denied. |
Status values
| Value | Name |
|---|---|
| 1 | Pending |
| 2 | Approved |
| 4 | Denied |
Error response
{
"status": 0,
"code": "403",
"errorCode": null,
"message": "9/17/2026 - 2:38:52 PM : You are not authorized to perform selected operation.",
"stackTrace": "",
"pagination": {
"pageNo": 0,
"pageSize": 0,
"totalRecords": 0,
"totalPages": 0,
"dataToken": ""
},
"validationErrors": null
}Returned when typeId isn't accessible to the company, or when employeeId isn't an employee at the company.
Approve Time Off Request
PUT https://api.worklio.com/wep/companies/{CLIENT_ID}/approved-timeoff-requests/{REQUEST_ID}
Requires an Admin-level token.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | The admin's note explaining the approval. Stored on the request's note field, not reason — see the callout below. |
reasonin this call maps tonoteon the request, notreason. The request object's ownreasonfield is the employee's reason from create, and is untouched by approval or denial.
Example request
require("dotenv").config();
const TOKEN = process.env.ADMIN_API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const REQUEST_ID = 28;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/approved-timeoff-requests/${REQUEST_ID}`;
const payload = {
reason: "Approved — coverage confirmed for that week."
};
async function approveTimeOffRequest() {
const response = await fetch(url, {
method: "PUT",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"content-type": "application/json",
"x-api-version": "2.0"
},
body: JSON.stringify(payload)
});
console.log(response.status);
console.log(await response.text());
}
approveTimeOffRequest();curl -s -X PUT "https://api.worklio.com/wep/companies/$CLIENT_ID/approved-timeoff-requests/28" \
-H "accept: application/json" \
-H "api-version: 2.0" \
-H "authorization: Bearer $ADMIN_API_KEY" \
-H "content-type: application/json" \
-H "x-api-version: 2.0" \
-d '{
"reason": "Approved — coverage confirmed for that week."
}' | jq .Example response
{
"id": 28,
"requestedOn": "2026-09-17T14:37:49Z",
"status": 2,
"employeeId": 4308,
"workLocationId": 1266,
"typeId": 7,
"payCodeType": 1,
"startOn": {
"item": "2026-09-16T05:00:00Z",
"withoutTime": false
},
"endOn": {
"item": "2026-09-16T10:00:00Z",
"withoutTime": false
},
"duration": 300,
"reason": "",
"note": "Approved — coverage confirmed for that week.",
"usedDuration": 0,
"resolvedBy": {
"firstName": "Marek",
"lastName": "Petrovaj"
},
"resolvedOn": "2026-09-17T14:50:05Z"
}resolvedBy identifies the admin who approved the request. resolvedOn is when the approval happened.
Deny Time Off Request
PUT https://api.worklio.com/wep/companies/{CLIENT_ID}/denied-timeoff-requests/{REQUEST_ID}
Requires an Admin-level token. Same request body as approving.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | The admin's note explaining the denial. Stored on the request's note field, same as approval. |
Example request
require("dotenv").config();
const TOKEN = process.env.ADMIN_API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const REQUEST_ID = 28;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/denied-timeoff-requests/${REQUEST_ID}`;
const payload = {
reason: "Denied — insufficient coverage during the requested week."
};
async function denyTimeOffRequest() {
const response = await fetch(url, {
method: "PUT",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"content-type": "application/json",
"x-api-version": "2.0"
},
body: JSON.stringify(payload)
});
console.log(response.status);
console.log(await response.text());
}
denyTimeOffRequest();curl -s -X PUT "https://api.worklio.com/wep/companies/$CLIENT_ID/denied-timeoff-requests/28" \
-H "accept: application/json" \
-H "api-version: 2.0" \
-H "authorization: Bearer $ADMIN_API_KEY" \
-H "content-type: application/json" \
-H "x-api-version: 2.0" \
-d '{
"reason": "Denied — insufficient coverage during the requested week."
}' | jq .Example response
{
"id": 28,
"requestedOn": "2026-09-17T14:37:49Z",
"status": 4,
"employeeId": 4308,
"workLocationId": 1266,
"typeId": 7,
"payCodeType": 1,
"startOn": {
"item": "2026-09-16T05:00:00Z",
"withoutTime": false
},
"endOn": {
"item": "2026-09-16T10:00:00Z",
"withoutTime": false
},
"duration": 300,
"reason": "",
"note": "Denied — insufficient coverage during the requested week.",
"usedDuration": 0,
"resolvedBy": {
"firstName": "Marek",
"lastName": "Petrovaj"
},
"resolvedOn": "2026-09-17T14:50:05Z"
}Updated 1 day ago
