Set a user's quota for a leave type
This API method sets a user's quota for one leave type, the same way as editing it on the user's page in the Vacation Tracker dashboard. Requires `users:write`. This is a full replacement of the quota settings for the chosen period: fields you omit take their defaults. - `amount` is in the company's unit: days, or hours when the company uses hourly accounting. This can differ from the `unit` that `GET /v2/users/{id}/quotas` returns for a leave policy set in the other unit. Up to 365 days or 2920 hours. It is required unless `unlimited` is `true`. - `unlimited: true` gives the user unlimited leave of this type; `amount` is then ignored. - `period` chooses the leave period to change: `current` (default) or `next`. Set `applyToFutureYears: true` to keep this quota in later periods too; by default only the chosen period changes. - `prorate` is allowed only for the user's first leave period (the one containing their start date); sending it for any other period fails with `400 PRORATE_NOT_ALLOWED`. When omitted, the user's prorate setting is left unchanged. The key owner (or `X-On-Behalf-Of` user) must be an admin, or a location admin who manages the user. It waits for the change and returns the user's quotas for the chosen period with `200`, or `202 Accepted` with an operation to poll. Errors: `400 VALIDATION_ERROR` (`details.fields`, including an `amount` above 365 days or 2920 hours), `400 QUOTA_PERIOD_NOT_AVAILABLE` (the requested period does not exist for the user; read `GET /v2/users/{id}/quotas?period=...` to check), `400 PRORATE_NOT_ALLOWED`, `403 ON_BEHALF_OF_NOT_ALLOWED`, `403 FORBIDDEN`, `404 RESOURCE_NOT_FOUND` (the user does not exist or is outside the key's data reach, or the leave type is not active for the user in the chosen period), and the `Idempotency-Key` codes.
Authorization
bearerAuth users:writeAPI 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: users:write
Path Parameters
resource ID.
leave type ID.
Header Parameters
optional key (1 to 255 printable ASCII characters) that makes a write request safe to retry. Keys are retained for 24 hours per API key. Retrying with the same key and the same request within those 24 hours replays the original response (with the Idempotent-Replayed header). Reusing the key with a different request returns 422 IDEMPOTENCY_KEY_REUSED; retrying while the first request is still running returns 409 IDEMPOTENCY_REQUEST_IN_PROGRESS; an invalid key returns 400 INVALID_IDEMPOTENCY_KEY.
1 <= length <= 255ID of the user the write is performed for. Requires the users:act-on-behalf scope, and the key owner must manage the target user; otherwise the request fails with 403 ON_BEHALF_OF_NOT_ALLOWED. Ignored on GET requests.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v2/users/string/quotas/string" \ -H "Content-Type: application/json" \ -d '{ "amount": 25, "applyToFutureYears": true }'{
"data": {
"userId": "user-cfe5d39b-f1f0-45aa-85cd-ce93e637a262",
"period": {
"start": "2026-01-01",
"end": "2026-12-31"
},
"quotas": [
{
"leaveTypeId": "leaveType-fcc1e5c5-ba93-479d-bd58-8f860ba10615",
"leaveTypeName": "Vacation",
"unlimited": false,
"amount": 25,
"unit": "days",
"isCustom": true,
"prorate": false,
"ignoreRolloverFromPreviousYear": false
},
{
"leaveTypeId": "leaveType-88681ca1-4a47-4e4d-bc35-ffff86c0f54e",
"leaveTypeName": "Sick leave",
"unlimited": true,
"amount": 0,
"unit": "days",
"isCustom": false,
"prorate": false,
"ignoreRolloverFromPreviousYear": false
}
]
}
}{
"operation": {
"id": "pa_3f1c2b9e-8a47-4d5e-9c61-2b7f0e4a1d93",
"status": "PENDING",
"url": "/v2/operations/pa_3f1c2b9e-8a47-4d5e-9c61-2b7f0e4a1d93"
}
}{
"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": "CONFLICT",
"name": "Conflict",
"description": "The request conflicts with the current state of the resource.",
"resolution": "Read the resource again and retry with up-to-date values.",
"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 quotas
This API method returns the quota (the base entitlement before rollover, seniority, TOIL and usage) of each leave type in the user's location, for one leave period. Use `GET /v2/users/{id}/balances` for remaining balances. Requires `users:read`. Each quota's `amount` is in that quota's `unit` (`days` or `hours`), as set on the leave policy or on the user's custom quota. `isCustom` is true when the quota was set for this user instead of coming from the location's leave policy. Only active leave types are included. A key without `leave-types:read-hidden` gets `Hidden Leave Type` as `leaveTypeName` for leave types hidden by the policy of the user's location; `leaveTypeId` and `amount` are unchanged. `period` is the only query parameter accepted; any other one fails validation. Errors: `400 VALIDATION_ERROR` (an invalid `period` or an unknown query parameter), `400 QUOTA_PERIOD_NOT_AVAILABLE` (the user has no leave period that contains today, or no next period), and `404 RESOURCE_NOT_FOUND` (the user does not exist or is outside the key's data reach).
List automations of a type
This API method returns every automation of the type in the path, active and paused, in one response without pagination. Requires `automations:read`. Automations are company-wide: they are not limited by the key's data reach. Each automation has the fields of its type; `Automation` lists one schema per type (for example `BlackoutPeriodAutomation` for `blackout-period`). `locationIds`, `departmentIds` and `labelIds` are always arrays, and an empty array means the automation applies to everyone; `entitlement-by-role` automations have no filters. Errors: `404 AUTOMATION_TYPE_NOT_FOUND` (`type` is not one of the automation types).