Consultants request time off; a manager approves or rejects it. A request covers a date range, belongs to a kind (holiday, sick leave, and so on, defined in the account’s settings), and moves through pending, approved, rejected, or cancelled.
Who does what
| Action | Role |
|---|---|
| Request own time off | Any user linked to a consultant profile |
| Request on someone’s behalf | Admin |
| Approve or reject | Admin (or the consultant’s team leader) |
| Cancel | The requester or an admin |
1. Create a request
A consultant requests for themselves; an admin passes consultant_id to request for someone else.
POST /time-off HTTP/1.1
Authorization: Bearer <access_token>
Content-Type: application/json
{
"kind": "paid_leave",
"start_date": "2026-02-16",
"end_date": "2026-02-20",
"reason": "Family trip"
}
Returns 201 Created with a TimeOffResponse:
{
"id": "0190a1c2-...",
"account_id": "0190a1c2-...",
"consultant_id": "0190a1c2-...",
"consultant_full_name": "Ada Lovelace",
"requested_by": "0190a1c2-...",
"kind": "paid_leave",
"start_date": "2026-02-16",
"end_date": "2026-02-20",
"half": null,
"reason": "Family trip",
"day_count": "5",
"status": "pending",
"decided_at": null,
"decided_by": null,
"rejection_reason": null,
"created_at": "2026-01-20T10:00:00Z"
}
The kind must be one of the keys configured for the account. day_count is computed from the range.
Half-days
When start_date equals end_date, you can request only part of the day by setting half to first (morning) or second (afternoon). Omit half for a full day. half is only valid for a single-day request.
{ "kind": "paid_leave", "start_date": "2026-02-16", "end_date": "2026-02-16", "half": "first" }
2. Approve or reject
POST /time-off/{id}/approve HTTP/1.1
Authorization: Bearer <access_token>
POST /time-off/{id}/reject HTTP/1.1
Authorization: Bearer <access_token>
Content-Type: application/json
{ "reason": "Clashes with the release week" }
Both return 200 OK. Approve sets status to approved and records who decided and when. Reject sets rejected and stores the reason.
3. Cancel
The requester (or an admin) can withdraw a request that has not been decided:
POST /time-off/{id}/cancel HTTP/1.1
Authorization: Bearer <access_token>
Returns 200 OK with status now cancelled.
Reading requests
GET /time-off lists them (paged), and GET /time-off/{id} returns one. Filter and scope behave as elsewhere (see Conventions).
Endpoints at a glance
| Action | Method | Path | Success |
|---|---|---|---|
| List | GET | /time-off | 200 |
| Get | GET | /time-off/{id} | 200 |
| Create | POST | /time-off | 201 |
| Approve | POST | /time-off/{id}/approve | 200 |
| Reject | POST | /time-off/{id}/reject | 200 |
| Cancel | POST | /time-off/{id}/cancel | 200 |