Skip to content

Request legal leave for yourself (user)

Request legal leave for yourself. Send the dates and the part of the first and last day you take; the server sizes each day from your work shift and places half days on the clock using the tenant's midday split (12:00 by default).

  • A full day needs only start_date.
  • A single day can be full, morning, afternoon, or hours with a start_time and end_time.
  • A range can start with the afternoon off and end with the morning off. Days in between are always full.

Weekends, public holidays and company special holidays in the range are not booked. The request always books legal leave: special leave and illness are recorded by HR, not through this endpoint.

The response has the same shape as an absences entry of the employee's request list, so the new request renders with the same code.

HTTP: bearerAuth

User bearer token. Default authentication for customer-facing endpoints. Obtain a token by calling POST /login with your credentials, then send it on every subsequent request as Authorization: Bearer <token>. The token inherits the permissions and PBX scope of the authenticated user.

HTTP Authorization Scheme
bearer
Bearer format
Bearer <token>
pbx path · string · uuid *
UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is refused with 403 rather than answered from another tenant.
employee path · string · uuid *
UUID of the Tempus employee whose queue this is. Must be the caller's own employee record: a queue is built from the approval rows addressed to one person, so another employee's id is refused rather than quietly answered with your own.
accept header · string
example: application/json

Request body · required · application/json

Request schema
start_date*string · date
First day of the leave.
example: 2026-08-10
end_datestring | null · date
Last day of the leave. Defaults to `start_date`.
example: 2026-08-12
first_daystring | null
Part of the first day taken. Defaults to `full`. On a range only `full` or `afternoon` (you work the morning, then leave). `morning` and `hours` are for a single day.
enum: full morning afternoon hours null
example: afternoon
last_daystring | null
Part of the last day taken, on a range only. Defaults to `full`. `morning` means you are back after midday. Leave it out on a single day.
enum: full morning null
example: morning
start_timestring | null
Start of a custom window (`HH:MM`). Required when `first_day` is `hours`, refused otherwise.
pattern: ^\d{2}:\d{2}$
example: 09:00
end_timestring | null
End of a custom window (`HH:MM`), after `start_time`. Required when `first_day` is `hours`, refused otherwise. The window is booked as is, capped at your scheduled time for the day.
pattern: ^\d{2}:\d{2}$
example: 11:00
company_idstring | null · uuid
Company the leave belongs to, one you have a contract with. Leave it out and the server uses the company of the contract covering the dates. Only needed when two contracts with different companies cover them; the request is refused with a 422 on `company_id` until you choose.
example: 550e8400-e29b-41d4-a716-446655440020
commentstring | null
Optional note for the validators.
length: 0–65535
example: Family trip

Responses

Created. The pending request and its approval progress. `request.requested_time` holds the seconds booked per working day, sized to your shift; `request.start` and `request.end` carry the clock time of a partial end.
Response schema
kind*string
Which request type this entry is. Selects the shape of `request`.
enum: absences
example: absences
request*object
A request stored as a Tempus transaction: absence, illness, special leave, legal holiday, home office, and removals of any of them. v2 of the payload. What changed from v1 and why: - **People are employees, never extensions.** v1 carried `ext_id`, a telephony extension id, on a Tempus record. It was the wrong identifier for this domain (an employee need not have an extension, and the field silently fell back to the employee id when they did not, so it meant two different things) and it cost two queries per row to produce. Everyone here is identified by `employee_id`. - **One identifier per thing.** v1 repeated one value as `employee_id`, `requester_id` and `creator_id`, and the request id as both `id` and `absence_request_id`. Also gone: `mxvp_user_id`, which was the pbx id under a name from another system, and `holiday_id`, which was always null. - **Stored values, not translated ones.** v1 renamed `absence` to `legal` and `approved` to `accepted` on the way out, so a client could not match what it read against what it sent, nor against the request type names the approval chain uses.
id*string · uuid
The request id, which the decision endpoints take. For home office this is one day-row: a request covering a week is stored as a row per day, each decided on its own.
example: 550e8400-e29b-41d4-a716-446655440010
type*string
The stored request type, not a renamed one.
enum: absence illness special legal_holiday home_office
example: absence
sub_typestring | null
`removal` when the request asks to take back days that were already approved, otherwise null.
status*string
The stored status.
enum: pending approved rejected cancelled pending_removal
example: pending
employee_id*string · uuid
The employee the request is for, whose balance and calendar it moves.
example: 550e8400-e29b-41d4-a716-446655440001
employeeobject | null
The same employee, by name, when the relation was loaded. Present on the validator queues, absent where the endpoint does not load it.
employee_idstring · uuid
first_namestring | null
last_namestring | null
namestring | null
example: Muller Anna
requested_byobject | null
Who raised the request, when that is somebody other than the employee it is for (raised on their behalf). Null for the ordinary case of raising your own, so a client can show provenance only when there is any.
employee_idstring · uuid
first_namestring | null
last_namestring | null
namestring | null
company_idstring | null · uuid
startstring | null · date-time
example: 2026-03-04T00:00:00+00:00
endstring | null · date-time
example: 2026-03-06T00:00:00+00:00
dates*array<string>
The days actually asked for, which is what to read rather than the range: a request can skip days.
[]string · date
requested_time*object
Seconds asked for per day, keyed by date.
Free-form object
requested_seconds*integer
The sum of `requested_time`, for convenience.
example: 57600
breakdownobject
Absences only (absent on home office rows). What the booked seconds mean for this employee: how many working days, how long one of their days is, and each day as the part a client sends when requesting (`full`, `morning`, `afternoon`, `hours`). A partial day is `morning` or `afternoon` when it is about half the employee's day and meets the midday split, otherwise `hours`.
working_days*number
Working days used, measured against this employee's own day. Can be fractional.
example: 2
seconds_per_day*integer
One full working day for this employee, in seconds. 0 when unknown.
example: 27360
first_day*string | null
Part of the first booked day. Null when no day is booked.
enum: full morning afternoon hours null
example: afternoon
last_day*string | null
Part of the last booked day. Same as `first_day` on a single day.
enum: full morning afternoon hours null
example: morning
partial_days*array<object>
Only the days booked for part of the day, date ascending: normally just the first and the last. Empty when every day is a full day; `requested_time` already lists each booked day and its seconds.
date*string · date
example: 2026-10-05
seconds*integer
Seconds booked that day.
example: 13680
part*string
enum: full morning afternoon hours
example: afternoon
start_time*string | null
`HH:MM` the absence starts, on a partial first day.
example: 12:00
end_time*string | null
`HH:MM` the absence ends, on a partial last day.
next_availabilityobject
When an employee is next at work **if the request carrying this object goes through**, next to what the general next-availability answer says today. The validator's view of a request: no second call, and no cache between the queue and the date. It is deliberately not the same question as `GET /user/{employee_id}/next-availability`: - **Anchored at the request, not at today**, so it reports the day *this* booking frees rather than the next free day counting from now. - **Counts what has been decided plus this one request.** The base is what has been signed off (accepted, plus an accepted absence somebody has asked to cancel — still time off until that cancellation is approved). Other queued requests are left out: they may be refused, and a date that moves because of a request this validator has not seen is not one they can act on. (`current` does count every pending row — that difference is intentional.) - **A removal reads as a reduction**, so its answer moves *earlier*, often into the past (`in_past`), which is the signal that the employee is already back. Absence, illness, special leave and legal holiday only. Home office never carries it: a home office day is governed by a weekly limit, not time off that moves an availability date. Neither does a request that can no longer move a date — `rejected`, `canceled` and `removed`. **Where it appears:** the absence lists (`/absences`, `/user/{employee_id}/absences`), the absence-request reads and writes (`/absence-requests`, `/user/{employee_id}/absence-requests` and its `POST`/`PUT`), `POST /user/{employee_id}/absence-removal-requests`, and both validator queues (`/validator/pending-requests` — on each `absence_requests[]` / `absence_removals[]` entry — and v2 `validator/queue`, on absence entries). It is **not** on the cancel responses (`POST .../absence-requests/{id}/cancel`), which report the outcome of an employee's own action rather than something a validator is weighing up. On the resource-backed payloads the key is **omitted** when there is nothing to say; on the v1 validator queue, whose entries are built by hand, it is always present and `null` in that case. Both mean the same thing.
if_approved*object
Availability as it would stand with this request applied.
absent_from*string | null · date
First day, today or later, that this request itself takes off. Null when it takes nothing off in the future: a removal request, or days that have all been and gone.
example: 2026-08-13
next_available_date*string | null · date
The day the employee is back at work under this scenario. Null only when no working day was found within the search horizon — an employee with no work shift, or one whose contract has ended.
example: 2026-08-17
next_available_at*string | null
Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down; null when only the date is meaningful.
available_now*boolean
Whether the employee is at work right now under this scenario. True together with a future `absent_from` is the ordinary case for a request that starts later.
example: 1
in_past*boolean
True when `next_available_date` is already behind us, i.e. approving this would not keep anybody away from now on. Render it as "already available" rather than as a return date.
example:
extends_current_absence*boolean
True when this request starts on the very day the employee would otherwise have come back, so it lengthens the absence already in place rather than opening a separate one. False for a request with working days in between — show `absent_from` as well as the return date in that case, or the return date reads as a contradiction of `available_now`.
example:
message*string | null
Ready-to-display line, already covering the three cases: `Available on 2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available (was back on 2026-08-03)`. Show it as returned.
example: Off from 2026-08-13, available on 2026-08-17
current*object
Today's general answer, unchanged — the same figure `GET /user/{employee_id}/next-availability` returns, so the two screens never disagree.
next_available_date*string | null · date
Next day the employee is available, counting from now. Null when they are available right now.
example: 2026-08-12
message*string | null
Ready-to-display line, or null while the employee is available.
example: Back on 2026-08-12
commentstring | null
The requester's note.
example: Family trip
createdstring | null · date-time
modifiedstring | null · date-time
validatorsarray<object>
Everyone this request asks, with their answer so far and where they sit, when the approvals relation was loaded. Rows superseded by a restarted chain are left out: they record what a previous round asked and are not people still to answer.
employee_idstring | null · uuid
namestring
The name frozen on the row when it was written, so a validator who has since been deleted still reads correctly.
example: Lemaire Farid
statusstring
enum: pending accepted rejected
commentstring | null
step_positioninteger | null
Their rung in the chain, or null for a supervisor, who sits outside the ladder.
example: 1
supervisorboolean
Whether they hold the request as a supervisor rather than as a step validator. v1 called this field `supervisor`.
mandatoryboolean
Whether their approval is required for the step to complete, whatever its quorum.
progress*object | null
Where a request stands in its approval chain: how far it has got, who moved it, and who it is waiting on. **Null when nobody was ever asked** - a request created already approved by an admin, or raised before approval chains existed and never given v1 rows. That is not the same as a chain waiting on nobody, which is an empty `waiting_on` on a real ladder. Read the request's own status for the outcome in that case, and show "no approval chain applied" rather than a ladder of zeroes. A request decided by the older v1 engine DOES get a block: it has no steps, so the ladder is empty, but `legacy` is true and `approved_by` names who answered. Names are the ones frozen on each approval row when it was written, so a validator who has since been deleted still reads correctly.
current_stepstring | null
The name of the step holding the request, or null when no step is active - either because it is settled or because there is no chain.
example: Team lead
steps_total*integer
How many steps this request's chain holds.
example: 3
steps_done*integer
How many of them are completed. With `steps_total` this is the "2 of 3" a status display shows.
example: 1
legacy*boolean
True for a request raised before approval chains existed. Worth reading: such a request has no steps and would otherwise look unconfigured rather than like an older one finishing where it started.
example:
waiting_on*array<object>
The validators still to answer at the step currently holding the request. Only that step: earlier ones are settled and later ones have not been asked. On a request decided by validator rules (`legacy: true`), every validator who has not answered yet. Empty on a settled request. One entry per person.
employee_id*string | null · uuid
The validator's employee id. Compare it with your own to tell whether the request waits on you.
example: 550e8400-e29b-41d4-a716-446655440031
name*string
Display name, frozen on the approval row when it was written.
example: Muller Jonas
approved_by*array<object>
Everyone who has approved so far, across every step and the supervisors. One entry per person.
employee_id*string | null · uuid
The approver's employee id.
example: 550e8400-e29b-41d4-a716-446655440030
name*string
Display name, frozen on the approval row when it was written.
example: Lemaire Farid
next_stepobject | null
The step that will be asked once the current one completes, or null when this is the last one. Lets a client say what happens next rather than only what is happening.
labelstring
example: HR
orderinteger
example: 2
steps*array<object>
The whole ladder, in the order it is asked.
orderinteger
This step's place in the chain, counting from 1.
example: 1
labelstring
The step's name, or a generated "Step n" when the chain left it unnamed.
example: Team lead
statusstring
`active` holds the request; `pending` has not been reached; `bypassed` was skipped, either because nobody on it covers this request type or because the request was settled above it.
enum: pending active completed bypassed rejected
example: completed
status_labelstring | null
The status as a sentence, already translated.
example: Approved by Lemaire Farid
passed_overboolean
Completed with nobody on this step answering - a supervisor settled the request, or an admin closed the chain. Worth drawing differently from a real approval.
example:
requiredinteger
How many approvals this step needs before it completes.
example: 1
approvedinteger
How many it has.
example: 1
validatorsarray<object>
employee_idstring | null · uuid
The validator's employee id.
example: 550e8400-e29b-41d4-a716-446655440030
namestring
example: Lemaire Farid
statusstring
enum: pending accepted rejected
example: accepted
mandatoryboolean
Their approval is required for the step to complete, whatever its quorum.
example:
supervisors*array<object>
People on the chain outside the ladder: told about the request, and where granted the power, able to settle it at any point. v1 calls these supervisors.
employee_idstring | null · uuid
The supervisor's employee id.
example: 550e8400-e29b-41d4-a716-446655440032
namestring
example: Weber Ines
statusstring
enum: pending accepted rejected
example: pending
can_decideboolean
Whether they may settle the request outright.
example: 1
Authorization Token Missing. This error is returned when the authorization token is missing.
Response schema
errorstring
Error message
example: Authorization Token is missing
Forbidden. The caller is outside this PBX, or asked for an employee record that is not their own.
Response schema
messagestring
example: You do not have access to this PBX.
Not found. No such employee in this PBX.
Response schema
messagestring
example: User not found.
Unprocessable. A field is invalid, a part does not fit the request (for example `morning` as the first day of a range), two companies cover the dates and no `company_id` was sent, another absence already holds one of the dates, or the range has no working day.
Response schema
messagestring
example: When your leave covers several days, the first day can only be a full day or an afternoon off.
errorsobject
Free-form object
companiesarray<object>
Only when the company is ambiguous (an error on `company_id`): the companies whose contracts cover the dates. Send one `id` back as `company_id`.
idstring · uuid
example: 550e8400-e29b-41d4-a716-446655440020
namestring
example: Sales Team
post https://cockpit.voxbi.com/api/v1/v2/{pbx}/employee/{employee}/requests/absences
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/v2/{pbx}/employee/{employee}/requests/absences' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"start_date":"2026-08-10"}'
const response = await fetch('https://cockpit.voxbi.com/api/v1/v2/{pbx}/employee/{employee}/requests/absences', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${YOUR_TOKEN}`,
  },
  body: JSON.stringify({
    "start_date": "2026-08-10"
}),
});

const data = await response.json();
console.log(data);
import requests

response = requests.post('https://cockpit.voxbi.com/api/v1/v2/{pbx}/employee/{employee}/requests/absences',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'},
    json={
    "start_date": "2026-08-10"
}
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$context = stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_TOKEN",
        'content' => '{
    \"start_date\": \"2026-08-10\"
}',
    ],
]);

$response = file_get_contents('https://cockpit.voxbi.com/api/v1/v2/{pbx}/employee/{employee}/requests/absences', false, $context);
$data = json_decode($response, true);
print_r($data);
Sample request
{ … }
"start_date": "2026-08-10"
}
No example for this status.
{ … }
"error": "Authorization Token is missing"
}
Cache-Control string
example: private, must-revalidate
Connection string
example: keep-alive
Content-Type string
example: application/json
Vary string
example: Origin
X-RateLimit-Limit integer
Max requests allowed in the current rate-limit window.
example: 60
X-RateLimit-Remaining integer
Requests remaining in the current rate-limit window.
example: 57
No example for this status.
No example for this status.
No example for this status.