User Assignments & Allocations
The assignment object
| Attribute | Type | Description |
|---|---|---|
user |
object | An object containing the id and name of the user. |
holiday_calendar |
object | Assigned holiday calendar (id, name) or null if unassigned. |
work_schedule |
object | Assigned active work schedule (id, name) or null if unassigned or deactivated. |
effective_work_schedule |
object | Effective schedule applied to the user (name, weekly_hours). |
The allocation object
| Attribute | Type | Description |
|---|---|---|
id |
integer | Unique ID for the allocation record. |
year |
integer | Allocation year. |
user |
object | An object containing the id and name of the user. |
pto_type |
object | An object containing the id, name, color, and icon of the policy. |
accrual_type |
string | Accrual type override if customized, otherwise null. |
accrual_schedule |
string | Accrual schedule override if customized, otherwise null. |
accrual_first_payday |
date | First payday override for accruals if customized. |
accrual_leave_hours |
decimal | Leave hours per accrual period if customized. |
accrual_worked_hours |
decimal | Worked hours base if customized. |
accrual_max_hours_per_year |
decimal | Maximum accrued hours cap per year if customized. |
days_per_year |
decimal | Annual allowance override in days if customized. |
carryover_days |
decimal | Carryover days override if customized. |
requires_approval |
boolean | Approval requirement override if customized. |
effective_days_per_year |
decimal | Effective days credited for the year. |
effective_accrual_type |
string | Effective accrual mode applied to the user. |
effective_accrual_schedule |
string | Effective accrual interval applied to the user. |
effective_requires_approval |
boolean | Effective approval requirement applied to the user. |
created_at |
datetime | Date and time the allocation was created. Use the ISO 8601 Format. |
updated_at |
datetime | Date and time the allocation was last updated. Use the ISO 8601 Format. |
Required permissions
The PTO API is currently being rolled out gradually. Requests from unavailable accounts return 403 Forbidden.
Only administrators can access, assign, or customize user holiday calendars, work schedules, and PTO allocations. Insufficient permissions will result in a 403 Forbidden status code.
List user assignments
Returns a list of users alongside their assigned holiday calendars, assigned work schedules, and effective working hours.
GET /v2/pto/assignments
| Parameter | Type | Description |
|---|---|---|
user_id |
integer | Filter by a single user ID. |
user_ids |
array of integers | Filter by multiple user IDs. |
Example Request:
curl "https://api.harvestapp.com/v2/pto/assignments?user_id=1782959" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"assignments": [
{
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"holiday_calendar": {
"id": 12,
"name": "US Holidays"
},
"work_schedule": {
"id": 8,
"name": "Standard Full Time"
},
"effective_work_schedule": {
"name": "Standard Full Time",
"weekly_hours": 40.0
}
}
]
}Update user assignments
Assigns or unassigns a holiday calendar and work schedule for a specific user. Returns an assignment object and a 200 OK response code.
PATCH /v2/pto/assignments/{USER_ID}
| Parameter | Type | Description |
|---|---|---|
holiday_calendar_id |
integer | ID of the holiday calendar to assign, or null to unassign. |
work_schedule_id |
integer | ID of the work schedule to assign, or null to unassign (reverting to company default). |
Example Request:
curl -X PATCH "https://api.harvestapp.com/v2/pto/assignments/1782959" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"holiday_calendar_id": 12, "work_schedule_id": 8}'
Example Response:
{
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"holiday_calendar": {
"id": 12,
"name": "US Holidays"
},
"work_schedule": {
"id": 8,
"name": "Standard Full Time"
},
"effective_work_schedule": {
"name": "Standard Full Time",
"weekly_hours": 40.0
}
}List user allocations
Returns a list of customized and yearly time off allocations across users.
The response contains an object with a pto_allocations property that contains an array of up to per_page allocations.
GET /v2/pto/allocations
| Parameter | Type | Description |
|---|---|---|
year |
integer | The allocation year (defaults to current year). |
user_ids |
array of integers | Filter allocations by user IDs. |
pto_type_ids |
array of integers | Filter allocations by time off policy IDs. |
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/allocations?year=2026&user_ids[]=1782959" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example Response:
{
"pto_allocations": [
{
"id": 780,
"year": 2026,
"accrual_type": null,
"accrual_schedule": null,
"accrual_first_payday": null,
"accrual_leave_hours": null,
"accrual_worked_hours": null,
"accrual_max_hours_per_year": null,
"days_per_year": 28.0,
"carryover_days": 2.0,
"requires_approval": false,
"effective_days_per_year": 28.0,
"effective_accrual_type": "fixed",
"effective_accrual_schedule": "monthly",
"effective_requires_approval": false,
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"created_at": "2026-09-03T12:00:00Z",
"updated_at": "2026-09-03T12: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/allocations?page=1&per_page=2000",
"next": null,
"previous": null,
"last": "https://api.harvestapp.com/v2/pto/allocations?page=1&per_page=2000"
}
}Update or reset a user allocation
Updates or resets per-user yearly allocation overrides. Returns an allocation object and a 200 OK response code when customized overrides are present or saved. When an allocation is reset to defaults (either by passing reset_to_default: true or when the submitted values match the policy defaults), the allocation override record is removed and a reset confirmation object is returned instead.
PATCH /v2/pto/allocations
| Parameter | Type | Description |
|---|---|---|
user_id |
integer | Required. The target user ID. |
pto_type_id |
integer | Required. The policy ID. |
year |
integer | The allocation year (defaults to current year). |
accrual_type |
string | Override accrual mode (fixed, accrued, unlimited). |
accrual_schedule |
string | Override accrual interval (monthly, biweekly, semimonthly, hourly). |
accrual_first_payday |
date | Anchor date when accrual_schedule is overridden to biweekly. |
accrual_leave_hours |
decimal | Leave hours earned per period when accrual_schedule is overridden to hourly. |
accrual_worked_hours |
decimal | Base worked hours required to earn leave when accrual_schedule is overridden to hourly. |
accrual_max_hours_per_year |
decimal | Annual cap on accrued leave hours when accrual_schedule is overridden to hourly. |
days_per_year |
decimal | Override annual allowance days. |
carryover_days |
decimal | Override carryover days for this year. |
requires_approval |
boolean | Override approval requirement. |
reset_to_default |
boolean | Pass true to delete customized overrides and revert to policy defaults. |
Example Request:
curl -X PATCH "https://api.harvestapp.com/v2/pto/allocations" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"user_id": 1782959, "pto_type_id": 101, "year": 2026, "days_per_year": 28.0}'
Example Response:
{
"id": 780,
"year": 2026,
"accrual_type": null,
"accrual_schedule": null,
"accrual_first_payday": null,
"accrual_leave_hours": null,
"accrual_worked_hours": null,
"accrual_max_hours_per_year": null,
"days_per_year": 28.0,
"carryover_days": 2.0,
"requires_approval": false,
"effective_days_per_year": 28.0,
"effective_accrual_type": "fixed",
"effective_accrual_schedule": "monthly",
"effective_requires_approval": false,
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"created_at": "2026-09-03T12:00:00Z",
"updated_at": "2026-09-03T12:05:00Z"
}Example Request (Reset to default):
curl -X PATCH "https://api.harvestapp.com/v2/pto/allocations" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"user_id": 1782959, "pto_type_id": 101, "year": 2026, "reset_to_default": true}'
Example Response (Reset to default):
{
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"year": 2026,
"customized": false,
"message": "Allocation reset to type defaults"
}Bulk update user allocations
Beta endpoint. Fully available, but the response shape may still change. Until it is frozen, every response includes
Harvest-Api-Stability: beta.
Updates or resets per-user yearly allocation overrides for many users in one request. Each item can also assign that person’s holiday calendar. All items are checked before the first write, and the writes share one transaction, so the batch applies as a whole or not at all. Returns a 200 OK response code.
PATCH /v2/pto/allocations/bulk
| Parameter | Type | Description |
|---|---|---|
allocations |
array | Required. A non-empty array of up to 2000 allocation objects. |
Each object in allocations accepts:
| Parameter | Type | Description |
|---|---|---|
user_id |
integer | Required. The target user ID. |
pto_type_id |
integer | Required. The policy ID. |
year |
integer | Required. The allocation year, between 2001 and 2099. |
accrual_type |
string | Override accrual mode (fixed, accrued, unlimited), or null to inherit. |
accrual_schedule |
string | Override accrual interval (monthly, biweekly, semimonthly, hourly), or null to clear. |
accrual_first_payday |
date | First biweekly payday in YYYY-MM-DD form, or null to clear. Any other spelling is refused. |
accrual_leave_hours |
decimal | Leave hours earned per period, or null to clear. |
accrual_worked_hours |
decimal | Base worked hours required to earn leave, or null to clear. |
accrual_max_hours_per_year |
decimal | Annual cap on accrued leave hours, or null to clear. |
days_per_year |
decimal | Override annual allowance days, or null to inherit. |
carryover_days |
decimal | Override carryover days; send 0 to clear. |
deferred_accrual |
boolean | Whether leave is earned in one year and usable the next, or null to inherit. |
requires_approval |
boolean | Override approval requirement, or null to inherit. |
reset_to_default |
boolean | Pass true to delete the overrides for the type and year. |
holiday_calendar_id |
integer or string | ID of the holiday calendar to assign, "none" or null to clear, or omitted to leave unchanged. |
Unlike PATCH /v2/pto/allocations, the batch refuses a value the single write would coerce: a malformed decimal override, calendar ID or payday, a boolean spelled any other way, a non-scalar attribute value, or a key the batch does not accept. An item that repeats the same user_id, pto_type_id and year is refused.
Example Request:
curl -X PATCH "https://api.harvestapp.com/v2/pto/allocations/bulk" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp ([email protected])" \
-d '{"allocations":[{"user_id":1782959,"pto_type_id":101,"year":2026,"days_per_year":28.0,"holiday_calendar_id":12},{"user_id":1782960,"pto_type_id":101,"year":2026,"reset_to_default":true}]}'
Example Response:
{
"pto_allocations": [
{
"id": 780,
"year": 2026,
"accrual_type": null,
"accrual_schedule": null,
"accrual_first_payday": null,
"accrual_leave_hours": null,
"accrual_worked_hours": null,
"accrual_max_hours_per_year": null,
"days_per_year": 28.0,
"carryover_days": 2.0,
"deferred_accrual": null,
"requires_approval": false,
"effective_days_per_year": 28.0,
"effective_accrual_type": "fixed",
"effective_accrual_schedule": "monthly",
"effective_deferred_accrual": false,
"effective_requires_approval": false,
"user": {
"id": 1782959,
"name": "Kim Allen"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"created_at": "2026-09-03T12:00:00Z",
"updated_at": "2026-09-03T12:05:00Z",
"holiday_calendar": {
"id": 12,
"name": "US Holidays"
}
},
{
"id": null,
"year": 2026,
"accrual_type": null,
"accrual_schedule": null,
"accrual_first_payday": null,
"accrual_leave_hours": null,
"accrual_worked_hours": null,
"accrual_max_hours_per_year": null,
"days_per_year": null,
"carryover_days": null,
"deferred_accrual": null,
"requires_approval": null,
"effective_days_per_year": 25.0,
"effective_accrual_type": "fixed",
"effective_accrual_schedule": "monthly",
"effective_deferred_accrual": false,
"effective_requires_approval": false,
"user": {
"id": 1782960,
"name": "Alex Rivera"
},
"pto_type": {
"id": 101,
"name": "Vacation",
"color": "blue",
"icon": "vacation"
},
"created_at": null,
"updated_at": null,
"holiday_calendar": null
}
]
}