Time Off Requests
The time off request object
| Attribute | Type | Description |
|---|---|---|
id |
integer | Unique ID for the time off request. |
status |
string | Status of request: pending, approved, declined, changes_requested, or cancelled. |
start_date |
date | Start date of the request. |
end_date |
date | End date of the request. |
days |
decimal | Total business days requested. |
business_days_at_submission |
decimal | Working days snapshot at the time of submission. |
start_time_minutes |
integer | Starting minute offset for partial-day requests (e.g. 540 for 09:00). |
end_time_minutes |
integer | Ending minute offset for partial-day requests (e.g. 780 for 13:00). |
notes |
string | Submitter notes for the request. |
review_reason |
string | Reason provided during manager or admin review. |
reviewed_at |
datetime | When the request was reviewed. |
created_at |
datetime | Date and time the request was created. Use the ISO 8601 Format. |
updated_at |
datetime | Date and time the request was updated. Use the ISO 8601 Format. |
user |
object | An object containing the id and name of the associated user. |
pto_type |
object | An object containing the id, name, color, and icon of the associated policy. |
reviewer |
object | An object containing the id and name of the reviewer, or null. |
request_days |
array | Array of daily breakdown objects (id, date, hours, day_fraction). |
Required permissions
The PTO API is currently being rolled out gradually. Requests from unavailable accounts return 403 Forbidden.
Administrators can list, view, create, edit, approve, decline, and cancel time off requests across the company.
Non-administrators can view, create, update, and cancel only their own time off requests. Requesting or querying another user’s requests will result in a 403 Forbidden status code.
List all time off requests
Returns a list of time off requests.
The response contains an object with a pto_requests property that contains an array of up to per_page time off requests. Each entry in the array is a separate time off request object. If no more requests are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your requests.
GET /v2/pto/requests
| Parameter | Type | Description |
|---|---|---|
user_id |
integer | Filter requests by user ID. Non-administrators can only pass their own user ID. |
status |
string | Filter requests by status (pending, approved, declined, changes_requested, cancelled). |
pto_type_id |
integer | Filter requests by time off policy ID. |
from |
date | Only return requests overlapping with or on/after this date. |
to |
date | Only return requests overlapping with or on/before this date. |
updated_since |
datetime | Only return requests updated since this timestamp. |
page |
integer | The page number to use in pagination. (Default: 1) |
per_page |
integer | The number of records to return per page. Can range between 1 and 2000. (Default: 2000) |
Example Request:
curl "https://api.harvestapp.com/v2/pto/requests?status=pending" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"pto_requests": [
{
"id": 501,
"status": "pending",
"start_date": "2026-10-01",
"end_date": "2026-10-02",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Fall break",
"review_reason": null,
"reviewed_at": null,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": null,
"request_days": [
{
"id": 1001,
"date": "2026-10-01",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
},
{
"id": 1002,
"date": "2026-10-02",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
}
]
}
],
"per_page": 2000,
"total_pages": 1,
"total_entries": 1,
"next_page": null,
"previous_page": null,
"page": 1,
"links": {
"first": "https://api.harvestapp.com/v2/pto/requests?page=1&per_page=2000",
"next": null,
"previous": null,
"last": "https://api.harvestapp.com/v2/pto/requests?page=1&per_page=2000"
}
}Retrieve a time off request
Retrieves the details of an existing time off request. Returns a time off request object and a 200 OK response code.
GET /v2/pto/requests/{PTO_REQUEST_ID}
Example Request:
curl "https://api.harvestapp.com/v2/pto/requests/501" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"id": 501,
"status": "pending",
"start_date": "2026-10-01",
"end_date": "2026-10-02",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Fall break",
"review_reason": null,
"reviewed_at": null,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": null,
"request_days": [
{
"id": 1001,
"date": "2026-10-01",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
},
{
"id": 1002,
"date": "2026-10-02",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
}
]
}Create a time off request
Creates a new time off request. Returns a time off request object and a 201 Created response code if the call succeeded.
POST /v2/pto/requests
| Parameter | Type | Description |
|---|---|---|
pto_type_id |
integer | Required. The policy ID to request time against. |
start_date |
date | Required. Start date for the request. |
end_date |
date | Required. End date for the request. |
user_id |
integer | Target user ID. Only administrators can submit on behalf of another user. |
notes |
string | Optional notes describing the request. |
start_time_minutes |
integer | Starting minute offset for partial-day requests. |
end_time_minutes |
integer | Ending minute offset for partial-day requests. |
conflict_resolution |
string | Either skip or replace to resolve overlapping requests. |
Example Request:
curl -X POST "https://api.harvestapp.com/v2/pto/requests" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"pto_type_id": 101, "start_date": "2026-11-05", "end_date": "2026-11-06", "notes": "Doctor appointment"}'
Example Response:
{
"id": 503,
"status": "pending",
"start_date": "2026-11-05",
"end_date": "2026-11-06",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Doctor appointment",
"review_reason": null,
"reviewed_at": null,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": null,
"request_days": [
{
"id": 1003,
"date": "2026-11-05",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
},
{
"id": 1004,
"date": "2026-11-06",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
}
]
}Update a time off request
Updates an unreviewed time off request. Only pending or changes_requested requests can be edited. Updating a request cancels the original request and returns a new replacement request object with a new id and a 200 OK response code.
PATCH /v2/pto/requests/{PTO_REQUEST_ID}
| Parameter | Type | Description |
|---|---|---|
pto_type_id |
integer | Updated policy ID. |
start_date |
date | Updated start date. |
end_date |
date | Updated end date. |
notes |
string | Updated notes. |
start_time_minutes |
integer | Updated start minute offset. |
end_time_minutes |
integer | Updated end minute offset. |
conflict_resolution |
string | Overlap resolution (skip or replace). |
Example Request:
curl -X PATCH "https://api.harvestapp.com/v2/pto/requests/502" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"notes": "Updated note"}'
Example Response:
{
"id": 503,
"status": "pending",
"start_date": "2026-11-05",
"end_date": "2026-11-06",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Updated note",
"review_reason": null,
"reviewed_at": null,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:20:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": null,
"request_days": [
{
"id": 1003,
"date": "2026-11-05",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
},
{
"id": 1004,
"date": "2026-11-06",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
}
]
}Cancel a time off request
Cancels a time off request. The request is not deleted from Harvest; instead, its status is updated to cancelled and it remains visible in request listings. Returns a 200 OK response code and the cancelled time off request object.
DELETE /v2/pto/requests/{PTO_REQUEST_ID}
Example Request:
curl -X DELETE "https://api.harvestapp.com/v2/pto/requests/503" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"id": 503,
"status": "cancelled",
"start_date": "2026-11-05",
"end_date": "2026-11-06",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Updated note",
"review_reason": null,
"reviewed_at": null,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:22:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": null,
"request_days": [
{
"id": 1003,
"date": "2026-11-05",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
},
{
"id": 1004,
"date": "2026-11-06",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-03T12:15:00Z",
"updated_at": "2026-09-03T12:15:00Z"
}
]
}Approve a time off request
Approves a pending or changes_requested request. Returns a time off request object and a 200 OK response code. Only administrators can perform this action.
POST /v2/pto/requests/{PTO_REQUEST_ID}/approve
Example Request:
curl -X POST "https://api.harvestapp.com/v2/pto/requests/501/approve" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"id": 501,
"status": "approved",
"start_date": "2026-10-01",
"end_date": "2026-10-02",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Fall break",
"review_reason": null,
"reviewed_at": "2026-09-03T12:25:00Z",
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-03T12:25:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": {
"id": 1782884,
"name": "Bob Powell"
},
"request_days": [
{
"id": 1001,
"date": "2026-10-01",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
},
{
"id": 1002,
"date": "2026-10-02",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
}
]
}Decline a time off request
Declines a time off request. Returns a time off request object and a 200 OK response code. Only administrators can perform this action.
POST /v2/pto/requests/{PTO_REQUEST_ID}/decline
| Parameter | Type | Description |
|---|---|---|
reason |
string | Optional decline reason. |
Example Request:
curl -X POST "https://api.harvestapp.com/v2/pto/requests/501/decline" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"reason": "Team coverage needed during that week"}'
Example Response:
{
"id": 501,
"status": "declined",
"start_date": "2026-10-01",
"end_date": "2026-10-02",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Fall break",
"review_reason": "Team coverage needed during that week",
"reviewed_at": "2026-09-03T12:30:00Z",
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-03T12:30:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": {
"id": 1782884,
"name": "Bob Powell"
},
"request_days": []
}Request changes on a time off request
Requests changes on a time off request. Returns a time off request object and a 200 OK response code. Only administrators can perform this action.
POST /v2/pto/requests/{PTO_REQUEST_ID}/request_changes
| Parameter | Type | Description |
|---|---|---|
reason |
string | Required. Explanation of changes required from the submitter. |
Example Request:
curl -X POST "https://api.harvestapp.com/v2/pto/requests/501/request_changes" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"reason": "Please adjust dates to start on Friday"}'
Example Response:
{
"id": 501,
"status": "changes_requested",
"start_date": "2026-10-01",
"end_date": "2026-10-02",
"days": 2.0,
"business_days_at_submission": 2.0,
"start_time_minutes": null,
"end_time_minutes": null,
"notes": "Fall break",
"review_reason": "Please adjust dates to start on Friday",
"reviewed_at": "2026-09-03T12:35:00Z",
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-03T12:35:00Z",
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"reviewer": {
"id": 1782884,
"name": "Bob Powell"
},
"request_days": [
{
"id": 1001,
"date": "2026-10-01",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
},
{
"id": 1002,
"date": "2026-10-02",
"hours": 8.0,
"day_fraction": 1.0,
"created_at": "2026-09-01T12:00:00Z",
"updated_at": "2026-09-01T12:00:00Z"
}
]
}