Voxbi Cockpit APIs
All endpoints

Create a schedule (user)

Creates a schedule. Requires a token whose validator holds the schedules-management permission, and every company, department or employee you select must be within that validator scope.

scope_type decides who the schedule is for and which selection field is required. It is optional: omit it and the department_id you send becomes a single-department scope, which is exactly how this endpoint behaved before scopes existed, so existing integrations need no change.

The schedule's anchor department (department in the response, group_id on the legacy list endpoint) is derived from the selection. When the selection resolves to no department at all, which happens for a company whose people hold contracts carrying no department, the schedule is saved without one and works normally: its people come from the company. Nothing is refused for lack of a department.

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_id path · string · uuid *
UUID of the PBX tenant.
accept header · string
example: application/json

Request body · required

Request schema
name*string
Display name of the schedule.
length: 0–150
example: Reception weekdays
scope_typestring
Who the schedule is for. Optional: when omitted the request behaves exactly as before scopes existed and `department_id` becomes the scope.
default: department
enum: company department employees
example: department
companiesarray<string>
Companies the schedule covers. Required when `scope_type` is `company`. Everyone currently contracted with these companies may be assigned, whether or not their contract carries a department. Each company must belong to your PBX and be within your validator scope.
items: 1–∞
[]string · uuid
UUID of a company.
departmentsarray<string>
Departments the schedule covers, replacing the single `department_id`. Used when `scope_type` is `department`; either this or `department_id` is required in that case. Each department must belong to your PBX and be within your validator scope.
items: 1–∞
[]string · uuid
UUID of a department.
employeesarray<string>
The exact people the schedule covers. Required when `scope_type` is `employees`. They may come from different departments and different companies. Each employee must be within your validator scope. The selection is stored as sent, but only those under a contract that is active today are actually assignable and returned in `employees`.
items: 1–∞
[]string · uuid
UUID of an employee.
department_idstring | null · uuid
The legacy single department. Required only when you send neither `scope_type` nor `departments`. Ignored for a company or employee scope, where the anchor department is derived from the selection.
example: 550e8400-e29b-41d4-a716-446655440001
days_of_week*array<integer>
Weekdays the schedule covers.
items: 1–∞
[]integer
ISO weekday number (1 = Monday through 7 = Sunday).
≥ 1≤ 7
day_start_time*string
Start of the daily window as `HH:MM`.
example: 08:00
day_end_time*string
End of the daily window as `HH:MM`. Must be after day_start_time.
example: 17:00
status_idstring | null · uuid
Default status for generated entries. Must belong to your PBX.
example: 550e8400-e29b-41d4-a716-446655440003
sub_status_idstring | null · uuid
Default sub-status. Must belong to the selected status.
status_filtersarray<string>
Statuses selectable on the grid. Each must belong to your PBX.
[]string · uuid
UUID of an allowed status.
is_activeboolean
Whether the schedule is active.
default: true
example: 1

Responses

The created schedule.
Response schema
id*string · uuid
Unique schedule identifier.
read-only
example: 550e8400-e29b-41d4-a716-446655440000
name*string
Human-readable name of the schedule template.
example: Sales Team Weekly Plan
departmentobject | null
The schedule's anchor department. Only present when the `department` relation is eager-loaded; otherwise this key is omitted. Null when the scope resolves to no department at all, which happens for a company-scoped schedule whose people hold contracts carrying no department. Such a schedule is valid and fully usable: its people come from the company. Treat this field as optional. Use `departments` for the full list of departments the schedule covers.
idstring · uuid
Unique identifier of the department.
example: 550e8400-e29b-41d4-a716-446655440001
namestring
Display name of the department.
example: Customer Support
scopeType*string
Who the schedule is for: - `company`: everyone contracted with the selected companies. - `department`: everyone contracted in the selected departments (the default, and what a schedule created without a `scope_type` gets). - `employees`: exactly the selected people, who may come from different departments and different companies.
enum: company department employees
example: department
scope*object
The raw selection the schedule was configured with. Only the list matching `scopeType` is populated; the other two are empty arrays. Use this to pre-populate an edit form so it round-trips.
companies*array<object>
Selected companies. Populated only when `scopeType` is `company`.
id*string · uuid
Unique identifier of the company.
example: 550e8400-e29b-41d4-a716-446655440020
name*string
Display name of the company.
example: Northwind Trading
departments*array<object>
Selected departments. Populated only when `scopeType` is `department`.
id*string · uuid
Unique identifier of the department.
example: 550e8400-e29b-41d4-a716-446655440001
name*string
Display name of the department.
example: Customer Support
employees*array<object>
Selected employees. Populated only when `scopeType` is `employees`.
id*string · uuid
Unique identifier of the employee.
example: 550e8400-e29b-41d4-a716-446655440010
fullName*string
Display name of the employee.
example: Jane Smith
departments*array<object>
Every department the schedule covers, resolved from the scope. For a company scope these are the companies' departments; for an employee scope the departments on the selected employees' contracts. An empty array when the scope resolves to no department.
id*string · uuid
Unique identifier of the department.
example: 550e8400-e29b-41d4-a716-446655440001
name*string | null
Display name of the department.
example: Customer Support
employees*array<object>
Everyone the schedule may assign, resolved from the scope. This is the pool the slot assignment pickers and auto-assign draw from; booking anybody outside it is refused with a 422. The same list is available on its own from `GET /{pbx_id}/schedule-management/{schedule}/employees`.
Each item — One assignable person of a schedule: an employee the schedule's scope covers and who may therefore be booked into its slots. Only employees holding a contract that is active today are listed — someone who has left, and someone whose contract has not started yet, is left out whatever the scope type, including a hand-picked `employees` selection. The schedule's `scope` still echoes the raw selection, so an edit form can round-trip what was picked. The department is the one on the employee's most recent contract, supplied so a picker can group or label its options when the schedule spans more than one department. Both department fields are null for an employee whose contract carries no department, which is normal for a company-scoped schedule.
id*string · uuid
Unique identifier of the employee.
example: 550e8400-e29b-41d4-a716-446655440010
fullName*string
Display name of the employee, ordered according to the tenant's first-name or last-name-first preference.
example: Jane Smith
departmentId*string | null · uuid
Identifier of the department on the employee's most recent contract. Null when that contract carries no department.
example: 550e8400-e29b-41d4-a716-446655440002
departmentName*string | null
Display name of the department on the employee's most recent contract. Null when that contract carries no department.
example: Customer Support
daysOfWeek*array<integer>
Weekdays covered by this schedule, stored as ISO 8601 weekday numbers (1 = Monday through 7 = Sunday). Returned as an empty array when no days are configured.
[]integer · int32
ISO 8601 weekday number (1 = Monday, 7 = Sunday).
enum: 1 2 3 4 5 6 7
example: 1
dayStartTime*string | null
Start of the daily working window in `HH:MM` 24-hour format (local wall-clock, no timezone). Null when no start time is configured.
example: 09:00
dayEndTime*string | null
End of the daily working window in `HH:MM` 24-hour format (local wall-clock, no timezone). Null when no end time is configured.
example: 17:30
slotDurationMinutes*integer · int32
Length in minutes of each bookable slot within the daily window. Defaults to the configured Tempus slot duration (typically 30) when not set.
example: 30
statusobject | null
Default status assigned to entries generated from this schedule. Only present when the `status` relation is eager-loaded; null when loaded but no default status is set, and omitted entirely when the relation is not loaded.
idstring · uuid
Unique identifier of the status.
example: 550e8400-e29b-41d4-a716-446655440002
namestring
Display name of the status.
example: Available
subStatusobject | null
Default sub-status assigned to entries generated from this schedule. Only present when the `subStatus` relation is eager-loaded; null when loaded but no default sub-status is set, and omitted entirely when the relation is not loaded.
idstring · uuid
Unique identifier of the sub-status.
example: 550e8400-e29b-41d4-a716-446655440003
namestring
Display name of the sub-status.
example: On Break
statusFilters*array<string>
Identifiers of the statuses that are selectable on this schedule's grid. Used to restrict which statuses planners may apply. Returned as an empty array when no filter is configured (all statuses allowed).
[]string · uuid
Identifier of an allowed status.
example: 550e8400-e29b-41d4-a716-446655440002
isActive*boolean
Whether the schedule is active. Inactive schedules are retained but not used to generate new planning entries.
example: 1
createdAt*string | null · date-time
ISO 8601 timestamp when the schedule was created.
read-only
example: 2024-03-01T08:29:07+00:00
updatedAt*string | null · date-time
ISO 8601 timestamp when the schedule was last updated.
read-only
example: 2024-03-01T08:29:07+00:00
Authorization Token Missing. This error is returned when the authorization token is missing.
Response schema
errorstring
Error message
example: Authorization Token is missing
The caller has no schedules-management scope, or the selection reaches beyond it. The message is "You do not have permission to manage schedules for this department." for a department (or a department resolved from a selected company) outside the scope, and "You do not have permission to manage this employee." for an employee outside it.
Response schema
No response body.
Unprocessable Parameters. This error is returned when a parameter is not valid.
Response schema
messagestring
example: The given data was invalid.
errorsobject
filterarray<string>
[]string
sortarray<string>
[]string
pagearray<string>
[]string
per_pagearray<string>
[]string
post https://cockpit.voxbi.com/api/v1/{pbx_id}/schedule-management
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/{pbx_id}/schedule-management' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"name":"Reception weekdays","scope_type":"department","departments":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"],"days_of_week":[1,2,3,4,5],"day_start_time":"08:00","day_end_time":"17:00"}'
const response = await fetch('https://cockpit.voxbi.com/api/v1/{pbx_id}/schedule-management', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${YOUR_TOKEN}`,
  },
  body: JSON.stringify({
    "name": "Reception weekdays",
    "scope_type": "department",
    "departments": [
        "550e8400-e29b-41d4-a716-446655440001",
        "550e8400-e29b-41d4-a716-446655440002"
    ],
    "days_of_week": [
        1,
        2,
        3,
        4,
        5
    ],
    "day_start_time": "08:00",
    "day_end_time": "17:00"
}),
});

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

response = requests.post('https://cockpit.voxbi.com/api/v1/{pbx_id}/schedule-management',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'},
    json={
    "name": "Reception weekdays",
    "scope_type": "department",
    "departments": [
        "550e8400-e29b-41d4-a716-446655440001",
        "550e8400-e29b-41d4-a716-446655440002"
    ],
    "days_of_week": [
        1,
        2,
        3,
        4,
        5
    ],
    "day_start_time": "08:00",
    "day_end_time": "17:00"
}
)
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' => '{
    \"name\": \"Reception weekdays\",
    \"scope_type\": \"department\",
    \"departments\": [
        \"550e8400-e29b-41d4-a716-446655440001\",
        \"550e8400-e29b-41d4-a716-446655440002\"
    ],
    \"days_of_week\": [
        1,
        2,
        3,
        4,
        5
    ],
    \"day_start_time\": \"08:00\",
    \"day_end_time\": \"17:00\"
}',
    ],
]);

$response = file_get_contents('https://cockpit.voxbi.com/api/v1/{pbx_id}/schedule-management', false, $context);
$data = json_decode($response, true);
print_r($data);
Sample request
{}
"name": "Reception weekdays",
"scope_type": "department",
"departments": [],
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002"
],
"days_of_week": [],
1,
2,
3,
4,
5
],
"day_start_time": "08:00",
"day_end_time": "17:00"
}
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.
{}
"errors": {}
"filter": [],
"The filter field must be an array."
],
"sort": [],
"The sort field must be a string."
],
"page": [],
"The page field must be an integer."
],
"per_page": []
"The per page field must be an integer."
]
}
}
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