Leave

Manage time-off types, requests, balances, and allocations via the API.

The Leave endpoints let you read and manage time off programmatically.

Call https://api.kuahr.com with the company’s authorised Live key in KUA_API_KEY. The SDKs use this address by default: Node or Python. Replace the illustrative IDs with real records from this company; the public API does not list employees. Persist an operation-specific idempotency key before writes and reuse the exact request on interrupted responses.

Leave types

The kinds of leave the company offers (Annual, Sick, …).

curl "https://api.kuahr.com/v1/leave/types" \
  -H "X-Api-Key: kua_live_your_key_here"
const types = await kua.leave.listTypes();
types = kua.leave.list_types()

Create one (leave:write):

curl "https://api.kuahr.com/v1/leave/types" \
  -X POST \
  -H "X-Api-Key: kua_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Annual leave", "defaultDaysPerYear": 20, "isPaid": true, "maxCarryoverDays": 5 }'
const type = await kua.leave.createType({
  name: "Annual leave",
  defaultDaysPerYear: 20,
  isPaid: true,
  maxCarryoverDays: 5,
});
leave_type = kua.leave.create_type(
    name="Annual leave", default_days_per_year=20, is_paid=True, max_carryover_days=5
)

Leave requests

List requests (filter by status and/or employeeId), then create, approve, reject, or cancel:

# List pending requests
curl "https://api.kuahr.com/v1/leave/requests?status=Submitted" \
  -H "X-Api-Key: kua_live_your_key_here"

# Submit a request
curl "https://api.kuahr.com/v1/leave/requests" \
  -X POST -H "X-Api-Key: kua_live_your_key_here" -H "Content-Type: application/json" \
  -d '{ "employeeId": "b2c3…", "leaveTypeId": "5e6f…", "startDate": "2026-08-03", "endDate": "2026-08-07", "reason": "Family trip" }'

# Choose one authorised decision and use the returned request ID.
case "$LEAVE_DECISION" in
  approve) curl -X POST "https://api.kuahr.com/v1/leave/requests/$REQUEST_ID/approve" -H "X-Api-Key: $KUA_API_KEY" ;;
  reject) curl -X POST "https://api.kuahr.com/v1/leave/requests/$REQUEST_ID/reject" -H "X-Api-Key: $KUA_API_KEY" -H "Content-Type: application/json" -d '{"comment":"Blackout period"}' ;;
  cancel) curl -X POST "https://api.kuahr.com/v1/leave/requests/$REQUEST_ID/cancel" -H "X-Api-Key: $KUA_API_KEY" ;;
  *) echo "Set one authorised LEAVE_DECISION before continuing" >&2; exit 1 ;;
esac
const pending = await kua.leave.listRequests({ status: "Submitted" });

const req = await kua.leave.createRequest({
  employeeId: "b2c3…",
  leaveTypeId: "5e6f…",
  startDate: "2026-08-03",
  endDate: "2026-08-07",
  reason: "Family trip",
});

// decision is ONE explicit authorised choice, not all three actions.
if (decision === "approve") await kua.leave.approveRequest(req.id);
else if (decision === "reject") await kua.leave.rejectRequest(req.id, "Blackout period");
else if (decision === "cancel") await kua.leave.cancelRequest(req.id);
pending = kua.leave.list_requests(status="Submitted")

req = kua.leave.create_request(
    employee_id="b2c3…", leave_type_id="5e6f…",
    start_date="2026-08-03", end_date="2026-08-07", reason="Family trip",
)

# Choose one authorised branch.
if decision == "approve":
    kua.leave.approve_request(req.id)
elif decision == "reject":
    kua.leave.reject_request(req.id, comment="Blackout period")
elif decision == "cancel":
    kua.leave.cancel_request(req.id)

Balances & allocations

Check an employee’s remaining days per type, and grant an allocation:

curl "https://api.kuahr.com/v1/leave/balances?employeeId=b2c3…&year=2026" \
  -H "X-Api-Key: kua_live_your_key_here"

curl "https://api.kuahr.com/v1/leave/allocations" \
  -X POST -H "X-Api-Key: kua_live_your_key_here" -H "Content-Type: application/json" \
  -d '{ "employeeId": "b2c3…", "leaveTypeId": "5e6f…", "year": 2026, "totalDays": 20 }'
const balances = await kua.leave.balances({ employeeId: "b2c3…", year: 2026 });
await kua.leave.grantAllocation({ employeeId: "b2c3…", leaveTypeId: "5e6f…", year: 2026, totalDays: 20 });
balances = kua.leave.balances(employee_id="b2c3…", year=2026)
kua.leave.grant_allocation(employee_id="b2c3…", leave_type_id="5e6f…", year=2026, total_days=20)

Events

You can also react to leave changes via webhooks: leave_request.submitted, leave_request.approved, leave_request.rejected.

Verify the chosen outcome

BranchRequired starting stateVerify
ApproveSubmitted, eligible request and approval authorityRequest is Approved; read its balances again
RejectSubmitted, explicit reason/commentRequest is Rejected; no approval is performed
CancelSubmitted or eligible Approved requestRequest is Cancelled; re-read balances

Cancellation uses POST /v1/leave/requests/{id}/cancel. The Node/Python methods above call that route. On an outdated-state conflict, refresh the request list and decide whether the intended action still applies instead of trying every branch. Overlapping dates, missing allocation or eligibility errors must be resolved from the returned code. Read available leave types and balances before requesting or allocating days; allocation is an explicit HR policy action, not a workaround for a denied request.

Done when: the selected request has the intended terminal state and balances agree. Types, requests and balances use leave:read; type creation, allocation and request decisions use leave:write plus endpoint policy. Continue with events or go-live readiness.

Search documentation

↑ ↓ to move · Enter to open · Esc to close