Vacation Tracker Docs
REST API v2API referenceUsers

Get 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).

GET
/v2/users/{id}/quotas

Authorization

bearerAuth users:read
AuthorizationBearer <token>

API 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:read

Path Parameters

id*string

resource ID.

Query Parameters

period?string

current returns the leave period that contains today, next returns the leave period after it. Default is current.

Default"current"
Value in"current" | "next"

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v2/users/string/quotas"
{
  "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
      }
    ]
  }
}
{
  "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": "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"
  }
}

Set a user's custom work week

This API method gives a user their own work week, overriding their location's work week. Requires `users:write`. This is a full replacement, not a merge. Send exactly one of: - `days` (the working days, 0 Sunday .. 6 Saturday, no duplicates), optionally with `workHours` to set the hours worked on each of those days; or - `schedule`, a rotating schedule of one or more `weeks`, each listing `{ day, hours }` per working day, starting from `schedule.startDate`. `workHours` needs `days`; `workHours` and each week of `schedule` list each day at most once. `workHours` and `schedule` are ignored, without an error, when the company's plan does not include custom work hours; only `days` is applied. 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 with `200`, or `202 Accepted` with an operation to poll. The response does not include the work week. Use `DELETE` to go back to the location's work week. Errors: `400 VALIDATION_ERROR` (`details.fields`, for example both or neither of `days` and `schedule`), `403 ON_BEHALF_OF_NOT_ALLOWED`, `403 FORBIDDEN`, `403 WORK_HOURS_LIMIT_REACHED` (the plan limit on custom work-hour configurations is reached), `404 RESOURCE_NOT_FOUND` (the user does not exist or is outside the key's data reach), and the `Idempotency-Key` codes.

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.