Vacation TrackerDeveloper Docs
REST API v2API referenceUsers

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

  • Only active leave types are included, in the order shown in the dashboard.
  • 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 every amount are unchanged.
  • For leave types with unlimited days, baseQuota, earned, quotaAtYearEnd and remaining are null.
  • period=current returns the leave year that contains today, or the latest leave year when none does; isCurrent tells which one it is.

Errors: 400 VALIDATION_ERROR (an invalid period) and 404 RESOURCE_NOT_FOUND (the user does not exist or is outside the key's data reach).

GET
/v2/users/{id}/balances

Authorization

bearerAuth balances: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: balances:read

Path Parameters

id*string

resource ID.

Query Parameters

period?string

current returns only the leave year that contains today (or the latest year if none does), all returns every leave year. Default is current.

Default"current"
Value in"current" | "all"

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/balances"
{
  "data": [
    {
      "userId": "user-63b17e97-d38b-4586-8498-bb4f5d2e2c14",
      "yearStart": "2026-01-01",
      "yearEnd": "2026-12-31",
      "isCurrent": true,
      "leaveTypes": [
        {
          "leaveTypeId": "leaveType-fcc1e5c5-ba93-479d-bd58-8f860ba10615",
          "leaveTypeName": "Vacation",
          "leavePolicyId": "leavePolicy-2d7c1b9e-5a4f-4c3b-8e1d-7f6a5b4c3d2e",
          "accrualType": "NONE",
          "unit": "days",
          "hasUnlimitedDays": false,
          "quotas": {
            "baseQuota": {
              "days": 20,
              "hours": 160,
              "isNegative": false
            },
            "rolloverFromPreviousYear": {
              "days": 3,
              "hours": 24,
              "isNegative": false
            },
            "seniorityEntitlement": {
              "days": 0,
              "hours": 0,
              "isNegative": false
            },
            "entitlementByRole": {
              "days": 0,
              "hours": 0,
              "isNegative": false
            },
            "toil": {
              "days": 1,
              "hours": 8,
              "isNegative": false
            },
            "toilLapsed": {
              "days": 0,
              "hours": 0,
              "isNegative": false
            },
            "earned": {
              "days": 21,
              "hours": 168,
              "isNegative": false
            },
            "quotaAtYearEnd": {
              "days": 20,
              "hours": 160,
              "isNegative": false
            },
            "expired": {
              "days": 0,
              "hours": 0,
              "isNegative": false
            },
            "used": {
              "days": 8,
              "hours": 64,
              "isNegative": false
            },
            "scheduled": {
              "days": 5,
              "hours": 40,
              "isNegative": false
            },
            "pending": {
              "days": 0,
              "hours": 0,
              "isNegative": false
            },
            "remaining": {
              "days": 16,
              "hours": 128,
              "isNegative": 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"
  }
}