Project a user's leave balance
This API method projects the balance of one leave type for a user over the current and the next leave year, and answers one of two questions. Requires balances:read.
Ask exactly one of:
date: the projected balance on that date. The answer isBALANCE, with the balance in days and hours.amounttogether withunit: the earliest time off of that size the balance covers. The answer isWINDOW, with the start date, the end date and the working days the window costs.unitisworkingfor working days,calendarfor calendar days andweeksfor weeks; acalendarorweekswindow is a fixed span of which only the working days count, so the same two weeks cost less when they contain a public holiday or a non-working day.
Sending neither date nor amount, both of them, or amount without unit, fails with 400 VALIDATION_ERROR.
A user that does not exist, is outside the key's data reach, or whose projection the key owner may not see, returns the same 404 RESOURCE_NOT_FOUND. A user with nothing to project (a leave type without a limit, no leave year covering today, or no working hours) returns 422 REQUEST_REJECTED.
When no window within the projection horizon covers the amount, the answer is NOT_ANSWERABLE with the horizon end date instead of a window. The projection reaches the end of the next leave year, which is also the horizonEnd of the response.
series carries the projected balance on each accrual date in ascending order, so a date between two points has the balance of the earlier one, and the drop at the leave year boundary is the part of the balance the rollover cap does not carry over.
The key owner can ask about themselves, about anyone in the company when they are an admin, about users in the locations they manage as a location admin, and about users in the departments they approve for. Any other user fails with 403 FORBIDDEN.
Errors: 400 VALIDATION_ERROR (details.fields), 403 FORBIDDEN (the key owner may not see this user's projection), 404 RESOURCE_NOT_FOUND (the user is outside the key's data reach, or the leave type does not exist for the user) and 422 REQUEST_REJECTED (the leave type has no limit, so there is no balance to project).
Authorization
bearerAuth balances:readAPI key sent as Authorization: Bearer vt_live_<secret>. See the Authentication and Scopes sections at the top of this document for how keys are created, which scopes exist and how the key owner's role limits them.
In: header
Scope: balances:read
Path Parameters
resource ID.
Query Parameters
the ID of the leave type to project.
the date to read the projected balance on, in YYYY-MM-DD format. Send it instead of amount and unit.
datethe size of the time off to find the earliest date for, greater than 0 and at most 1000. Requires unit, and is sent instead of date.
0 < value <= 1000the unit of amount. Only working days count in every unit; calendar and weeks fix the span of the window instead of its cost.
"working" | "calendar" | "weeks"Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v2/users/string/projection?leaveTypeId=leaveType-fcc1e5c5-ba93-479d-bd58-8f860ba10615"{
"data": {
"userId": "user-63b17e97-d38b-4586-8498-bb4f5d2e2c14",
"leaveTypeId": "leaveType-fcc1e5c5-ba93-479d-bd58-8f860ba10615",
"question": {
"type": "DATE",
"date": "2027-04-15"
},
"answer": {
"type": "BALANCE",
"date": "2027-04-15",
"days": 6.67,
"hours": 53.36
},
"series": [
{
"date": "2026-11-01",
"days": 1.67,
"hours": 13.36
},
{
"date": "2026-12-01",
"days": 3.34,
"hours": 26.72
},
{
"date": "2027-01-01",
"days": 5,
"hours": 40
},
{
"date": "2027-02-01",
"days": 1.67,
"hours": 13.36
},
{
"date": "2027-03-01",
"days": 3.34,
"hours": 26.72
},
{
"date": "2027-04-01",
"days": 5,
"hours": 40
}
],
"horizonEnd": "2027-12-31"
}
}{
"error": {
"code": "VALIDATION_ERROR",
"name": "ValidationError",
"description": "A query parameter, body field or header failed validation.",
"resolution": "Fix the fields listed in details.fields and send the request again.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"details": {
"fields": [
{
"path": "startDate",
"message": "\"startDate\" is required"
}
]
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"name": "Unauthorized",
"description": "The API key is missing, malformed or not recognized.",
"resolution": "Send a valid API key in the Authorization header as Bearer followed by the full vt_live_ key.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef"
}
}{
"error": {
"code": "INSUFFICIENT_SCOPE",
"name": "InsufficientScope",
"description": "The API key does not have the scopes this request needs.",
"resolution": "Add the scopes listed in details.requiredScopes to the key in the Vacation Tracker dashboard.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"details": {
"requiredScopes": [
"leaves:write"
]
}
}
}{
"error": {
"code": "RESOURCE_NOT_FOUND",
"name": "ResourceNotFound",
"description": "The requested resource does not exist or is outside the data this key can access.",
"resolution": "Check the ID of the resource named in details.resource and that the key owner can see it.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef"
}
}{
"error": {
"code": "LEAVE_NEGATIVE_BALANCE",
"name": "LeaveNegativeBalance",
"description": "The user does not have enough balance for this leave.",
"resolution": "Shorten the leave, use a different leave type, or ask an admin to adjust the quota.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef"
}
}{
"error": {
"code": "RATE_LIMITED",
"name": "RateLimited",
"description": "Too many requests were sent in a short time.",
"resolution": "Wait a few seconds and retry, using the same Idempotency-Key for writes.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"name": "InternalError",
"description": "Something went wrong on our side.",
"resolution": "Retry later, and if it keeps happening, contact Vacation Tracker support and quote the requestId.",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef"
}
}Need help?
developers@vacationtracker.ioGet a user's leave balances
This API method returns the leave balances of a user, calculated the same way as in the Vacation Tracker dashboard, one entry per leave year. Requires balances:read. The list is not paginated.
List a user's labels
This API method returns the labels assigned to a user. Requires labels:read. Labels are company-wide, so this works for any user of the company, whatever the key's data reach. The list is not paginated.