Creating time off requests

Time off request API Overview

This guide explains how to create a time off request using the Oyster Public API.

Note for Reseller partners using the API - you will need to use the X-Oyster-Customer-Id header for all of the calls in this guide. For more information, see the Reseller guide to using the Oyster API.

Definitions

Time off request: a record representing a team member’s request for time away from work (for example, vacation, sick leave, unpaid leave, or other leave types), for a specific date range.

Time Off Request Lifecycle & Capabilities

  • A time off request is created via the API and then typically moves through a workflow such as pending → approved/rejected → canceled depending on actions taken by admins and the team member.
  • After a request is created, it can be retrieved and managed with other Time Off endpoints (for example, retrieve, approve, reject, cancel).

1. Creating a time off request

Create a new time off request record with the Create time off request endpoint.

The API supports creating time off requests in two units: days and hours.

1.1. Creating time off request with days unit

Single day request

When creating single day request firstDayDuration field is required.

Example request

curl --request POST \
     --url https://api.oysterhr.com/v1/time_off/requests/ \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
    "engagementId": "eng123",
    "startDate": "2026-03-16", 
    "endDate": "2026-03-16"
    "type": "VACATION"
    "reason": "PAID_TIME_OFF",
    "requestByAdmin": false,
    "firstDayDuration": "FULL_DAY",
    "lastDayDuration": null,
    "firstDayDurationInHours": null,
    "lastDayDurationInHours": null,
    "requesterComments": null
}
'

Multi day request

When creating multi day request firstDayDuration and lastDayDuration fields are required

Example request

curl --request POST \
     --url https://api.oysterhr.com/v1/time_off/requests/ \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
    "engagementId": "eng123",
    "startDate": "2026-03-16", 
    "endDate": "2026-03-17"
    "type": "VACATION"
    "reason": "PAID_TIME_OFF",
    "requestByAdmin": false,
    "firstDayDuration": "FULL_DAY",
    "lastDayDuration": "MORNING",
    "firstDayDurationInHours": null,
    "lastDayDurationInHours": null,
    "requesterComments": null
}
'

1.2. Creating time off request with hours unit

Request in hours

  • Multi-day request: firstDayDurationInHours and lastDayDurationInHours

Single day request

When creating single day request firstDayDurationInHours field is required.

curl --request POST \
     --url https://api.oysterhr.com/v1/time_off/requests/ \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
    "engagementId": "eng123",
    "startDate": "2026-03-16", 
    "endDate": "2026-03-16"
    "type": "VACATION"
    "reason": "PAID_TIME_OFF",
    "requestByAdmin": false,
    "firstDayDuration": null,
    "lastDayDuration": null,
    "firstDayDurationInHours": 8,
    "lastDayDurationInHours": null,
    "requesterComments": null
}
'

Multi day request

When creating multi day request firstDayDuration and lastDayDuration fields are required

curl --request POST \
     --url https://api.oysterhr.com/v1/time_off/requests/ \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
    "engagementId": "eng123",
    "startDate": "2026-03-16", 
    "endDate": "2026-03-17"
    "type": "VACATION"
    "reason": "PAID_TIME_OFF",
    "requestByAdmin": false,
    "firstDayDuration": null,
    "lastDayDuration": null,
    "firstDayDurationInHours": 8,
    "lastDayDurationInHours": 4,
    "requesterComments": null
}
'

1.3. Time off types and reasons mapping

The time off request creation endpoint includes type and reason attributes, so it is important to understand which reason values can be used with each type.

Here is the type and reason mapping:

  • VACATION
    • PAID_TIME_OFF
  • SICK_LEAVE
    • PAID_TIME_OFF
    • UNPAID_TIME_OFF
  • UNPAID_LEAVE
    • PARENTAL_LEAVE
    • CAREGIVER_LEAVE
    • EDUCATIONAL_LEAVE
    • MARRIAGE_LEAVE
    • MILITARY_TRAINING_ASSEMBLY
    • MILITARY_MEDICAL_EXAMINATION
    • MILITARY_UNPAID_LEAVE
    • SABBATICAL
    • CIVIC_DUTIES
    • RELIGIOUS_OBSERVANCE
    • BEREAVEMENT
    • OTHER_UNPAID_LEAVE
  • OTHER
    • PARENTAL_LEAVE
    • CAREGIVER_LEAVE
    • EDUCATIONAL_LEAVE
    • MARRIAGE_LEAVE
    • MILITARY_TRAINING_ASSEMBLY
    • MILITARY_MEDICAL_EXAMINATION
    • MILITARY_PAID_LEAVE
    • SABBATICAL
    • CIVIC_DUTIES
    • BEREAVEMENT
    • TIME_OFF_IN_LIEU
    • LOCAL_HOLIDAY
    • OTHER_PAID_LEAVE

When requesterCommentsare required

In most cases requesterComments are optional, however they are required for specific cases when it’s not possible to understand the true reason of the request, which is important for payroll.

Those type and reason combinations are:

  • UNPAID_LEAVE
    • OTHER_UNPAID_LEAVE
  • OTHER
    • OTHER_PAID_LEAVE

Exceptions

  • For team members located in Brazil:
    • requesting time off in their first year of employment is not allowed, as per the local law
    • requesting more vacation leave compared to their balance is prevented
  • Team members are prevented from submitting time off requests in the past. Only administrators are allowed to request this
  • Requesting half days is prevented for the following countries and leave types:
    • All leave types:
      • Bulgaria
      • Brazil
      • Colombia
      • Germany
      • Ecuador
      • Greece
      • Hungary
      • Mexico
      • Poland
      • Romania
      • Serbia
    • Sick leave:
      • Spain
      • Italy
      • Peru
    • Vacation:
      • Sweden