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

MethodNameEndpoint
POSTCreate Time Off Requesthttps://api.worklio.com/wep/companies/{CLIENT_ID}/timeoff-requests
PUTApprove Time Off Requesthttps://api.worklio.com/wep/companies/{CLIENT_ID}/approved-timeoff-requests/{REQUEST_ID}
PUTDeny Time Off Requesthttps://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

FieldTypeRequiredDescription
employeeIdintegerYesThe employee this request is for.
typeIdintegerYesThe time off request type this request is filed under.
startOnobjectYesStart of the requested time off. See startOn/endOn object below.
durationinteger (minutes)YesLength of the request, in minutes.
reasonstringNoOptional note from the employee explaining the request.

startOn / endOn object

FieldTypeDescription
itemstringA date ("2026-09-16") or an ISO 8601 datetime.
withoutTimebooleanWhether 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.

withoutTime isn't preserved as sent. Even if you send startOn.item as a bare date with withoutTime: true, the response echoes back a resolved UTC datetime with withoutTime: false. Don't rely on withoutTime staying true in 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

FieldTypeDescription
idintegerUnique identifier for the request. This is the REQUEST_ID used to approve or deny it.
requestedOnstring (datetime)When the request was submitted.
statusinteger (enum)See Status values below.
employeeIdintegerThe employee the request is for.
workLocationIdintegerThe employee's work location. Set automatically from the employee record.
typeIdintegerThe time off request type this request was filed under.
payCodeTypeinteger (enum)Pay code category, set automatically from typeId. See Pay Code Type values in Time Off Request Types.
startOn / endOnobjectStart and end of the requested time off. endOn is computed from startOn + duration.
durationinteger (minutes)Length of the request.
reasonstringThe employee's reason for the request, if one was given on create.
notestringSet when the request is approved or denied — see below. Empty until then.
usedDurationinteger (minutes)How much of this request's duration has been used so far.
resolvedByobjectPresent only after the request has been approved or denied. See Approve/Deny below.
resolvedOnstring (datetime)Present only after the request has been approved or denied.

Status values

ValueName
1Pending
2Approved
4Denied

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

FieldTypeRequiredDescription
reasonstringYesThe admin's note explaining the approval. Stored on the request's note field, not reason — see the callout below.

reason in this call maps to note on the request, not reason. The request object's own reason field 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

FieldTypeRequiredDescription
reasonstringYesThe 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"
}

Did this page help you?