{"openapi":"3.2.0","info":{"title":"Voxbi Cockpit API","version":"0.1.0","x-logo":{"url":"logos\/Voxbi_Cockpit_Logo_RGB.svg","altText":"Voxbi Logo"},"description":"REST API for the Voxbi Cockpit PBX platform. Use it to manage users, extensions, SIP devices, phone numbers, call flows, IVRs, queues, schedules, and related telephony resources.\n\nAll resources are scoped to a PBX tenant. The authenticated identity determines which PBX(es) you can access.\n\nEvery request must be authenticated. See **Authentication** for the available schemes.\n\n## Principal-conditional fields\n\nMost resources are reachable by two kinds of token: a **user-owned** token\n(the cockpit\/mobile Bearer token) and a **PBX-owned API key** (created on the\nIntegrations page). A few response fields are *per-user* and therefore depend\non which kind of token you use: they are returned for user-owned tokens and\n**omitted entirely** for PBX API-key tokens (a PBX has no per-user state).\nSuch fields are flagged **PRINCIPAL-CONDITIONAL** in their description -\nexamples: `is_favorite` on extensions and contacts, and `editable` on contacts.\n\n## Embedding related resources\n\nList and detail endpoints accept an `?include=` query parameter: a\ncomma-separated list of related resources to embed. Each endpoint documents\nits own allowed values; anything not in that allow-list is rejected, and\nnothing is embedded unless you ask for it.\n\nSome relations are **dot-nested**, which lets you choose how deep to go. For\nexample, on an extension you can request `user` to embed just the user, or\n`user.groups` to embed the user **and** its groups (you do not have to load\nthe parent separately). Combine several with commas, e.g.\n`?include=user.groups,sipDevice`.\n\n## Rate limiting\n\nRequests are rate limited per API key (per PBX). The default budget is 120\nrequests per minute; it may be higher depending on your plan. Every response\nreports your current budget so you do not have to hard-code the number:\n\n- `X-RateLimit-Limit` - the limit applied to this request\n- `X-RateLimit-Remaining` - requests left in the current window\n\nWhen you exceed the limit the API responds with `429 Too Many Requests` and a\n`Retry-After` header (seconds to wait before retrying). Always read these\nheaders rather than assuming a fixed rate: the budget can change per plan, and\na few endpoints have their own stricter limit. The clearest example is\n**Push the PBX configuration**, which is capped at 1 request per minute - that\nendpoint documents its own limit and `429` response.\n","termsOfService":"https:\/\/www.voxbi.com\/legal","contact":{"name":"Voxbi Cockpit API Support","url":"https:\/\/www.voxbi.com\/contact","email":"team-voxbi@mixvoip.com"},"license":{"name":"Proprietary","url":"https:\/\/www.voxbi.com\/legal"}},"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api\/v1","description":"The production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/api\/v1","description":"The staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/api\/v1","description":"The development API server"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Bearer <token>","description":"**User bearer token.** Default authentication for customer-facing endpoints.\nObtain a token by calling `POST \/login` with your credentials, then send it\non every subsequent request as `Authorization: Bearer <token>`. The token\ninherits the permissions and PBX scope of the authenticated user."},"ApiKeyAuth":{"type":"apiKey","name":"Authorization","in":"header","x-internal":true},"PbxServerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Bearer <token>","description":"Auth for Pbx server","x-internal":true},"PbxApiKey":{"type":"http","scheme":"bearer","bearerFormat":"Bearer <pbx_api_key>","description":"PBX API key, used by the customer's PBX server (e.g. for roaming login\/logout)"},"IntegrationApiKey":{"type":"http","scheme":"bearer","description":"API key created on the Cockpit **Integrations** page (an \"API key\" integration).\nIt is a bearer token owned by the customer's PBX and limited to the scopes\nselected when the key was created (e.g. `phone-numbers`, `push-configuration`).\n\nSend it in the `Authorization` header:\n\n```\nAuthorization: Bearer <api_key>\n```\n\nManage keys (create \/ reveal \/ revoke) from **Integrations \u2192 New integration \u2192\nAPI key**.\n"}},"schemas":{"Twinning":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}},"InCallState":{"type":"object","description":"A user's live \"on a call right now\" flag, owned by Cockpit and reported by the\nclient itself (`POST \/in-call`).\n\nThe flag is deliberately short-lived: a `true` is trusted for `ttl_seconds` only\n(one hour by default) and then decays back to `false`, so a client that never\nreports the hang-up cannot leave the user marked in-call indefinitely. Reading a\nuser who has reported nothing inside that window is not an error: it presents as\n`in_call: false` with null timestamps.\n","required":["user_id","in_call","in_call_updated_at","expires_at","ttl_seconds"],"properties":{"user_id":{"type":"string","format":"uuid","description":"The user the flag belongs to (always the bearer token's own user).","example":"550e8400-e29b-41d4-a716-446655440000"},"in_call":{"type":"boolean","description":"Whether the user is currently reported as being on a call.","example":true},"in_call_updated_at":{"type":["string","null"],"format":"date-time","description":"When the flag was last reported, or null if nothing was reported inside the window.","example":"2026-08-03T09:14:22+00:00"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the current value stops being trusted and reverts to false, or null when there\nis no live value. Refreshed on every report.\n","example":"2026-08-03T10:14:22+00:00"},"ttl_seconds":{"type":"integer","description":"How long (seconds) a reported flag is trusted before it decays to false.","example":3600}}},"TempusTransaction":{"type":"object","description":"Absence request as serialized by the V1 `TempusTransactionResource`. Backed by\na single `TempusTransaction` ledger row, this object represents an employee\nabsence (legal holiday, home office, illness, special leave, overtime balance)\ntogether with its approval status and requested period.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Several values are remapped from internal storage to the API\ncontract: the internal `approved`, `rejected`, and `cancelled` statuses are\nexposed as `accepted`, `rejected`, and `canceled`; the internal `absence` type\nis exposed as `legal`. Other status and type values pass through unchanged.\n\n`employee_id` is the canonical id of the employee the request belongs to.\nSeveral identifier fields are intentionally redundant for client convenience:\n`requester_id` and `creator_id` both return that same employee id, and\n`absence_request_id` mirrors `id`. `ext_id` is a different value - the\nemployee's extension id (see below). `holiday_id` is reserved for future use\nand is always null.\n","required":["id","mxvp_user_id","employee_id","requester_id","creator_id","ext_id","company_id","absence_request_id","holiday_id","status","type","sub_type","start","end","requested_time","working_days","total_seconds","workshift_seconds_per_day","is_half_day","starts_half_day","ends_half_day","start_time","end_time","working_day_details","comment","accepted_by","created","modified"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique absence request (transaction) identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns this absence request. Mirrors the\ntransaction's `pbx_id`. Null for records not bound to a specific tenant.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Canonical identifier of the Tempus employee this request belongs to. This\nis the value the `filter[employee_id]` query parameter matches against.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"requester_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee the absence belongs to. Returns the same\nvalue as `employee_id` and `creator_id`.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"creator_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee who owns the absence. Returns the same\nvalue as `requester_id` (the owning employee, not the acting principal).\n","example":"550e8400-e29b-41d4-a716-446655440002"},"ext_id":{"type":["string","null"],"description":"External system identifier of the employee, resolved from the linked\nemployee record. Null when the employee has no external mapping.\n","example":"EXT-10293"},"company_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus company the absence is attributed to. Null when\nthe request is not scoped to a specific company.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"absence_request_id":{"type":"string","format":"uuid","description":"Alias of `id`, provided for clients that reference absence requests by this\nfield name. Always equal to `id`.\n","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"holiday_id":{"type":["string","null"],"format":"uuid","description":"Reserved for a future link to a public-holiday record. Always null in the\ncurrent API version.\n","example":null},"status":{"type":["string","null"],"enum":["pending","accepted","rejected","canceled","pending_removal","removed"],"description":"Approval status of the absence request, remapped for the API: internal\n`approved` is returned as `accepted` and internal `cancelled` as `canceled`.\n`pending` awaits validation, `pending_removal` and `removed` track removal\nof a previously approved absence. Null only for records with no status set.\n","example":"pending"},"type":{"type":"string","enum":["legal","home_office","illness","special","overtime_balance"],"description":"Category of the absence. The internal `absence` type is remapped to `legal`\n(legal holiday). `home_office` is a remote-work day, `illness` is sick\nleave, `special` is special leave, and `overtime_balance` is an\novertime-balance adjustment.\n","example":"legal"},"sub_type":{"type":["string","null"],"description":"Optional sub-classification of the absence (for example `removal` for a\nremoval request, or a computed\/rollover marker for ledger adjustments).\nNull when the request carries no sub-type.\n","example":"removal"},"start":{"type":["string","null"],"format":"date-time","description":"Start of the absence period as an ISO 8601 timestamp. Null when the request\nhas no start date.\n","example":"2024-03-01T00:00:00+00:00"},"end":{"type":["string","null"],"format":"date-time","description":"End of the absence period as an ISO 8601 timestamp. Null when the request\nhas no end date.\n","example":"2024-03-05T00:00:00+00:00"},"requested_time":{"type":["object","null"],"description":"Per-day breakdown of the requested time, stored as a map of date strings to\ndurations in seconds. Used to compute the effective amount while the request\nis pending. Null when no per-day breakdown was supplied.\n\nSeconds are the employee's own scheduled day, not a nominal 8h: a part-timer on\na 4h day books `14400` for a full day off, and a half of that day is `7200`.\nOnly working days appear: a weekend, public holiday or company special holiday\ninside the range is omitted.\n\nRows written before that was true carry a `0` entry for each such day, and rows\ncreated over this API before it carried a flat `28800` regardless of shift. So\ndo **not** count these keys to get the length of a request and do not assume the\nseconds match the shift on historical rows: read `working_days` and\n`workshift_seconds_per_day`, which normalize both shapes.\n","additionalProperties":{"type":"integer","format":"int32","description":"Requested duration for that day, in seconds."},"example":{"2024-03-01":28800,"2024-03-04":28800,"2024-03-05":14400}},"working_days":{"type":"number","description":"How long the request is, in working days the employee actually consumes:\nweekends, public holidays, company special holidays and days already taken by\nanother absence are excluded, and each remaining day is measured against that\nemployee's own scheduled day. A part-timer's 4h day therefore counts as `1`,\nwhile 4h out of an 8h day counts as `0.5`.\n\nThis is the same figure the approval debits from the employee's balance, so it\nnever disagrees with the amount charged. Prefer it over deriving a length from\n`start`\/`end`: that difference is exclusive (Aug 3 \u2192 Aug 7 is 5 days, not 4) and\ncounts days nobody works.\n\nWhole counts serialize without a fractional part (`5`, not `5.0`); half days\nappear as `.5`.\n","example":4.5},"total_seconds":{"type":"integer","format":"int32","description":"Sum of the booked seconds in `requested_time`, i.e. the same period expressed as\ntime rather than days. `0` when the request has no per-day breakdown.\n","example":129600},"workshift_seconds_per_day":{"type":"integer","format":"int32","description":"What one full working day is worth for this employee, in seconds. It is the yardstick\nevery booked day is measured against. `28800` on a standard 8h shift, `14400` for\nsomebody contracted to 4h days. Use it to render a booking as a fraction of a day\nwithout assuming 8h.\n","example":28800},"is_half_day":{"type":"boolean","description":"True when either end of the request is a half day. The single flag a list badge\nneeds; `starts_half_day` \/ `ends_half_day` say which end.\n","example":true},"starts_half_day":{"type":"boolean","description":"True when the first day is a half day: the employee works that morning and\nleaves. `start_time` then carries the hour they leave.\n","example":true},"ends_half_day":{"type":"boolean","description":"True when the last day is a half day: the absence covers that morning and the\nemployee is back after it. `end_time` then carries the hour they return.\n\nOn a single-day half day both this and `starts_half_day` are true, and both hours\nare filled in.\n","example":false},"start_time":{"type":["string","null"],"description":"Local wall-clock hour (`HH:MM`) the absence begins on a half-day start. Null when\nthe request does not start on a half day. Taken from the request's own stored\ntime when it has one, otherwise the tenant's configured AM\/PM split\n(`TEMPUS_HALF_DAY_SPLIT`, default `12:00`).\n","example":"14:00"},"end_time":{"type":["string","null"],"description":"Local wall-clock hour (`HH:MM`) the absence ends on a half-day end. Null when the\nrequest does not end on a half day. Same source as `start_time`.\n","example":"18:00"},"working_day_details":{"type":"array","description":"Per-day breakdown of the request, working days only, in date order. The same\ndays as `requested_time` with the half-day verdict and hours resolved per day.\n\nHours only ever land on the two ends: a day in the middle of a range has no clock\ntime of its own, and a single-day request is both ends at once.\n","items":{"type":"object","required":["date","seconds","is_half_day","start_time","end_time"],"properties":{"date":{"type":"string","format":"date","description":"The day, as `YYYY-MM-DD`.","example":"2026-08-03"},"seconds":{"type":"integer","format":"int32","description":"Seconds booked off on this day, scaled to the employee's own scheduled day.\n","example":14400},"is_half_day":{"type":"boolean","description":"True when this day's booked seconds fall short of a full day for this\nemployee (see `workshift_seconds_per_day`), allowing 15 minutes of\ntolerance for lunch and rounding.\n","example":true},"start_time":{"type":["string","null"],"description":"Hour (`HH:MM`) the absence starts on this day. Non-null only on a half-day\nfirst day (or a single-day half day).\n","example":"12:00"},"end_time":{"type":["string","null"],"description":"Hour (`HH:MM`) the absence ends on this day. Non-null only on a half-day\nlast day (or a single-day half day).\n","example":null}}}},"comment":{"type":["string","null"],"description":"Free-form note attached to the absence request (mirrors the transaction's\n`note`). Null when no comment was provided.\n","example":"Family event, returning Wednesday afternoon."},"accepted_by":{"type":"array","description":"Every validator that must sign off on this request, with their individual\ndecision. One entry per approval record; empty when the request has no\nassigned validators yet. A request is fully accepted only once every entry\nreports `accepted`.\n","items":{"type":"object","required":["employee_id","status"],"properties":{"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus employee acting as validator for this\napproval.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"status":{"type":"string","enum":["pending","accepted","rejected"],"description":"This validator's decision. `pending` awaits their action; `accepted`\nand `rejected` record the outcome.\n","example":"pending"}}}},"next_availability":{"type":"object","description":"When an employee is next at work **if the request carrying this object goes through**,\nnext to what the general next-availability answer says today. The validator's view of a\nrequest: no second call, and no cache between the queue and the date.\n\nIt is deliberately not the same question as `GET \/user\/{employee_id}\/next-availability`:\n\n- **Anchored at the request, not at today**, so it reports the day *this* booking frees\n  rather than the next free day counting from now.\n- **Counts what has been decided plus this one request.** The base is what has been\n  signed off (accepted, plus an accepted absence somebody has asked to cancel \u2014 still\n  time off until that cancellation is approved). Other queued requests are left out:\n  they may be refused, and a date that moves because of a request this validator has not\n  seen is not one they can act on. (`current` does count every pending row \u2014 that\n  difference is intentional.)\n- **A removal reads as a reduction**, so its answer moves *earlier*, often into the past\n  (`in_past`), which is the signal that the employee is already back.\n\nAbsence, illness, special leave and legal holiday only. Home office never carries it: a\nhome office day is governed by a weekly limit, not time off that moves an availability\ndate. Neither does a request that can no longer move a date \u2014 `rejected`, `canceled` and\n`removed`.\n\n**Where it appears:** the absence lists (`\/absences`, `\/user\/{employee_id}\/absences`), the\nabsence-request reads and writes (`\/absence-requests`, `\/user\/{employee_id}\/absence-requests`\nand its `POST`\/`PUT`), `POST \/user\/{employee_id}\/absence-removal-requests`, and both\nvalidator queues (`\/validator\/pending-requests` \u2014 on each `absence_requests[]` \/\n`absence_removals[]` entry \u2014 and v2 `pending-requests\/absences`). It is **not** on the\ncancel responses (`POST ...\/absence-requests\/{id}\/cancel`), which report the outcome of an\nemployee's own action rather than something a validator is weighing up.\n\nOn the resource-backed payloads the key is **omitted** when there is nothing to say; on\nthe v1 validator queue, whose entries are built by hand, it is always present and `null`\nin that case. Both mean the same thing.\n","required":["if_approved","current"],"properties":{"if_approved":{"type":"object","description":"Availability as it would stand with this request applied.","required":["absent_from","next_available_date","next_available_at","available_now","in_past","extends_current_absence","message"],"properties":{"absent_from":{"type":["string","null"],"format":"date","description":"First day, today or later, that this request itself takes off. Null when it takes\nnothing off in the future: a removal request, or days that have all been and gone.\n","example":"2026-08-13"},"next_available_date":{"type":["string","null"],"format":"date","description":"The day the employee is back at work under this scenario. Null only when no\nworking day was found within the search horizon \u2014 an employee with no work shift,\nor one whose contract has ended.\n","example":"2026-08-17"},"next_available_at":{"type":["string","null"],"description":"Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down;\nnull when only the date is meaningful.\n","example":null},"available_now":{"type":"boolean","description":"Whether the employee is at work right now under this scenario. True together with\na future `absent_from` is the ordinary case for a request that starts later.\n","example":true},"in_past":{"type":"boolean","description":"True when `next_available_date` is already behind us, i.e. approving this would\nnot keep anybody away from now on. Render it as \"already available\" rather than as\na return date.\n","example":false},"extends_current_absence":{"type":"boolean","description":"True when this request starts on the very day the employee would otherwise have\ncome back, so it lengthens the absence already in place rather than opening a\nseparate one. False for a request with working days in between \u2014 show\n`absent_from` as well as the return date in that case, or the return date reads as\na contradiction of `available_now`.\n","example":false},"message":{"type":["string","null"],"description":"Ready-to-display line, already covering the three cases: `Available on\n2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available\n(was back on 2026-08-03)`. Show it as returned.\n","example":"Off from 2026-08-13, available on 2026-08-17"}}},"current":{"type":"object","description":"Today's general answer, unchanged \u2014 the same figure\n`GET \/user\/{employee_id}\/next-availability` returns, so the two screens never disagree.\n","required":["next_available_date","message"],"properties":{"next_available_date":{"type":["string","null"],"format":"date","description":"Next day the employee is available, counting from now. Null when they are\navailable right now.\n","example":"2026-08-12"},"message":{"type":["string","null"],"description":"Ready-to-display line, or null while the employee is available.","example":"Back on 2026-08-12"}}}},"example":{"if_approved":{"absent_from":"2026-08-13","next_available_date":"2026-08-17","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-13, available on 2026-08-17"},"current":{"next_available_date":"2026-08-12","message":"Back on 2026-08-12"}}},"created":{"type":["string","null"],"format":"date-time","description":"Timestamp when the absence request was created, as an ISO 8601 string. Null\nwhen not set.\n","example":"2024-02-15T10:00:00+00:00","readOnly":true},"modified":{"type":["string","null"],"format":"date-time","description":"Timestamp when the absence request was last updated, as an ISO 8601 string.\nNull when not set.\n","example":"2024-02-16T09:30:00+00:00","readOnly":true}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440001","employee_id":"550e8400-e29b-41d4-a716-446655440002","requester_id":"550e8400-e29b-41d4-a716-446655440002","creator_id":"550e8400-e29b-41d4-a716-446655440002","ext_id":"550e8400-e29b-41d4-a716-446655440009","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440000","holiday_id":null,"status":"accepted","type":"legal","sub_type":null,"start":"2026-08-03T00:00:00+00:00","end":"2026-08-05T00:00:00+00:00","requested_time":{"2026-08-03":14400,"2026-08-04":28800,"2026-08-05":28800},"working_days":2.5,"total_seconds":72000,"workshift_seconds_per_day":28800,"is_half_day":true,"starts_half_day":true,"ends_half_day":false,"start_time":"12:00","end_time":null,"working_day_details":[{"date":"2026-08-03","seconds":14400,"is_half_day":true,"start_time":"12:00","end_time":null},{"date":"2026-08-04","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-05","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":"Family event, returning Thursday.","accepted_by":[{"employee_id":"550e8400-e29b-41d4-a716-446655440004","status":"accepted"}],"next_availability":{"if_approved":{"absent_from":"2026-08-03","next_available_date":"2026-08-06","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-03, available on 2026-08-06"},"current":{"next_available_date":null,"message":null}},"created":"2026-07-28T10:00:00+00:00","modified":"2026-07-29T09:30:00+00:00"}},"TempusTransactionApproval":{"type":"object","description":"Approval (validation) record for a Tempus absence request, as serialized by the\nV1 `TempusTransactionApprovalResource`. Each record represents one validator's\ndecision on a single absence request (`tempus_transaction_id`): whether it is\nstill pending, accepted, or rejected, together with an optional comment.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Several keys are renamed projections of model attributes:\n`mxvp_user_id` is the tenant identifier (`pbx_id`), `absence_request_id` is the\nrelated transaction id (`tempus_transaction_id`), and `comment` is the stored\n`note`. The `ext_id` field is a computed extension identifier resolved from the\nvalidator. The `validator` object is only present when the `validator` relation\nis loaded on the model; when absent the key is omitted entirely. The\n`holiday_id` key is always returned but currently always null (reserved for\nfuture use).\n","required":["id","mxvp_user_id","absence_request_id","ext_id","status","comment","create_time","modified","holiday_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the approval record.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns this approval record (the model's\n`pbx_id`). May be null for records not bound to a specific tenant.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"absence_request_id":{"type":"string","format":"uuid","description":"Identifier of the absence request this approval belongs to (the related\nTempus transaction id).\n","example":"550e8400-e29b-41d4-a716-446655440002"},"ext_id":{"type":["string","null"],"description":"Extension identifier of the validating employee, computed from the\nvalidator. Null when the validator has no associated extension.\n","example":"201"},"validator":{"type":"object","description":"Summary of the employee who is responsible for this validation. Only\npresent when the `validator` relation is loaded on the model; otherwise the\nkey is omitted from the response.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the validating employee.","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Display name of the validating employee, falling back to the linked\nuser's name when the employee has no name of its own. May be null.\n","example":"Jane Smith"}}},"status":{"type":"string","enum":["pending","accepted","rejected"],"description":"Current decision on the absence request: `pending` while awaiting the\nvalidator, `accepted` when approved, or `rejected` when declined.\n","example":"pending"},"comment":{"type":["string","null"],"description":"Optional free-form note left by the validator explaining the decision (the\nmodel's `note`). Null when no comment was provided.\n","example":"Approved, please coordinate handover with the team."},"create_time":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp of when the approval record was created.","example":"2024-03-01T08:29:07+00:00","readOnly":true},"modified":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp of when the approval record was last updated.","example":"2024-03-01T09:15:42+00:00","readOnly":true},"holiday_id":{"type":["string","null"],"format":"uuid","description":"Reserved for a future link to a holiday record. Always returned but\ncurrently always null.\n","example":null}}},"TempusCorrection":{"type":"object","description":"A Tempus time-point correction request as serialized by the V1\n`CorrectionResource`. A correction captures a requested change to an\nemployee's recorded time point (its time, status, or sub-status), the values\nbefore and after the change, the approval workflow state, and a count of how\nmany validators have accepted or refused it.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Two timestamp columns are renamed in the payload:\n`created_at` is exposed as `create_time` and `updated_at` as `update_time`.\nThe `mxvp_user_id` key carries the owning Pbx (tenant) identifier (the\nmodel's `pbx_id`). The `requester_ext_id` key is the requesting employee's\nidentifier.\n\nThe nested `timepoint` object is only present when the related time point is\nloaded on the model; when present, its `status` and `substatuses` members are\nthemselves only included when those relations are loaded.\n","required":["id","mxvp_user_id","timepoint_id","requester_ext_id","new_status_id","new_sub_status_id","old_status_id","old_sub_status_id","new_time","old_time","correction_comment","new_comment","status","create_time","update_time","accepted_validations_count","refused_validations_count","accepted_by"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the correction request.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this correction (the model's pbx_id).","example":"550e8400-e29b-41d4-a716-446655440001"},"timepoint_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the time point this correction targets. Null when the\ncorrection requests the creation of a brand new time point rather than a\nchange to an existing one.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"requester_ext_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee who requested the correction. Resolved from the\nrelated requester employee when loaded, falling back to the stored\nemployee_id. Null when no requesting employee can be determined.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"new_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status the time point should be changed to. Null\nwhen the correction does not change the status.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"new_sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus sub-status the time point should be changed to.\nNull when the correction does not change the sub-status.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"old_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status the time point had before the correction.\nNull when no prior status applies.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"old_sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus sub-status the time point had before the\ncorrection. Null when no prior sub-status applies.\n","example":"550e8400-e29b-41d4-a716-446655440007"},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Location the correction asks the time point to be recorded at. Null when\nthe correction does not touch the location, which is NOT the same as asking\nfor the location to be cleared: acceptance leaves the time point's current\nlocation exactly as it is. Always null on corrections raised before this\nfield existed.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"old_location_id":{"type":["string","null"],"format":"uuid","description":"The location the time point was pointed at when the correction was raised.\nA snapshot, so the requested move reads as old -> new and so the reversal\ncreated by cancelling an accepted correction can swap the pair. Null when\nthe time point had no location, or when the correction adds a new one.\n","example":"550e8400-e29b-41d4-a716-446655440011"},"old_location":{"type":["object","null"],"description":"The location the time point was pointed at when the correction was raised,\nresolved. Null when it had none.\n","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440011"},"name":{"type":"string","example":"HQ Luxembourg"},"latitude":{"type":["number","null"],"format":"double","example":49.6008},"longitude":{"type":["number","null"],"format":"double","example":6.133},"geofence_radius_m":{"type":["integer","null"],"example":150}}},"new_location":{"type":["object","null"],"description":"The location the correction asks for, resolved. Null when the correction\ndoes not touch the location.\n","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","example":"Remote office"},"latitude":{"type":["number","null"],"format":"double","example":49.612},"longitude":{"type":["number","null"],"format":"double","example":6.13},"geofence_radius_m":{"type":["integer","null"],"example":200}}},"new_time":{"type":["string","null"],"format":"date-time","description":"Requested new timestamp for the time point, in ISO 8601 format. A null\nvalue on a correction targeting an existing time point indicates a removal\n(deletion) request.\n","example":"2024-03-01T09:00:00.000000Z"},"old_time":{"type":["string","null"],"format":"date-time","description":"Original timestamp of the time point before the correction, in ISO 8601\nformat. Null when no prior time applies.\n","example":"2024-03-01T08:30:00.000000Z"},"correction_comment":{"type":["string","null"],"description":"Free-form justification supplied by the requester explaining why the\ncorrection is needed. Null when no comment was given.\n","example":"Forgot to clock out at the end of the shift."},"new_comment":{"type":["string","null"],"description":"Comment to be applied to the time point when the correction is accepted\n(used in particular when creating a new time point). Null when not set.\n","example":"Manual entry approved by supervisor."},"status":{"type":["string","null"],"enum":["pending","accepted","rejected","canceled","rejected_closed"],"description":"Workflow state of the correction request. `pending` awaits validator\nreview, `accepted` has been approved and applied to the time point,\n`rejected` was refused, `canceled` was withdrawn, and `rejected_closed`\nwas refused and closed. Legacy stored values `refused` and `refused_closed`\nare normalized to `rejected` and `rejected_closed` respectively.\n","example":"pending"},"create_time":{"type":"string","format":"date-time","description":"Timestamp when the correction request was created, in ISO 8601 format (the model's created_at).","example":"2024-03-01T08:29:07.000000Z","readOnly":true},"update_time":{"type":"string","format":"date-time","description":"Timestamp when the correction request was last updated, in ISO 8601 format (the model's updated_at).","example":"2024-03-01T08:29:07.000000Z","readOnly":true},"accepted_validations_count":{"type":"integer","format":"int32","description":"Number of validators who have accepted this correction request.","example":1},"refused_validations_count":{"type":"integer","format":"int32","description":"Number of validators who have refused this correction request.","example":0},"accepted_by":{"type":"array","description":"Every validator that must sign off on this correction, with their\nindividual decision. A correction may require multiple validators. One\nentry per approval record; empty when no validators are assigned yet.\n","items":{"type":"object","required":["employee_id","status"],"properties":{"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus employee acting as validator.","example":"550e8400-e29b-41d4-a716-446655440004"},"status":{"type":"string","enum":["pending","accepted","rejected"],"description":"This validator's decision. `pending` awaits their action; `accepted`\nand `rejected` record the outcome.\n","example":"pending"}}}},"timepoint":{"type":"object","description":"The time point this correction targets. Only present when the related\ntime point is loaded on the model; absent otherwise.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the time point.","example":"550e8400-e29b-41d4-a716-446655440002","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the time point.","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee the time point belongs to. Resolved from the\nrelated employee when loaded, falling back to the time point's user\nidentifier. Null when neither is available.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status currently assigned to the time point.","example":"550e8400-e29b-41d4-a716-446655440004"},"time":{"type":["string","null"],"format":"date-time","description":"Start timestamp of the time point, in ISO 8601 format. Null when not set.","example":"2024-03-01T08:30:00.000000Z"},"migration_id":{"type":["string","null"],"description":"Legacy migration identifier carried in the time point metadata, used to\ntrace records imported from a previous system. Null when not migrated.\n","example":"legacy-tp-10293"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp of the time point, in ISO 8601 format. Null when\nthe time point has not been deleted.\n","example":null},"status":{"type":"object","description":"The Tempus status assigned to the time point. Only present when the\nstatus relation is loaded; absent otherwise.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440004","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the status.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Display name of the status.","example":"Working"},"icon":{"type":["string","null"],"description":"CSS icon class used to represent the status, from its style metadata. Null when not set.","example":"la la-briefcase"},"fontcolor":{"type":["string","null"],"description":"Font color (CSS color value) for the status label, from its style metadata. Null when not set.","example":"#ffffff"},"backgroundcolor":{"type":["string","null"],"description":"Background color (CSS color value) for the status badge, from its style metadata. Null when not set.","example":"#2e7d32"},"css":{"type":["string","null"],"description":"Additional CSS class applied to the status badge, from its style metadata. Null when not set.","example":"status-working"},"comment":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether a comment is required when assigning this status, normalized\nfrom the status metadata to an integer flag (0 = not required,\n1 = required).\n","example":0},"payable":{"type":["boolean","null"],"description":"Whether time recorded under this status is payable. Null when not configured.","example":true},"action":{"type":["string","null"],"description":"Optional action keyword associated with the status, from its metadata. Null when none.","example":"clock_in"},"migration_id":{"type":["string","null"],"description":"Legacy migration identifier for the status, from its metadata. Null when not migrated.","example":"legacy-status-7"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp of the status, in ISO 8601 format. Null when not deleted.","example":null}}},"substatuses":{"type":"array","description":"Sub-statuses attached to the time point. Only present when the\nsub-status relation is loaded; may be empty.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440005","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the sub-status.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Display name of the sub-status.","example":"Client meeting"},"icon":{"type":["string","null"],"description":"CSS icon class used to represent the sub-status, from its style metadata. Null when not set.","example":"la la-users"},"fontcolor":{"type":["string","null"],"description":"Font color (CSS color value) for the sub-status label, from its style metadata. Null when not set.","example":"#000000"},"backgroundcolor":{"type":["string","null"],"description":"Background color (CSS color value) for the sub-status badge, from its style metadata. Null when not set.","example":"#bbdefb"},"css":{"type":["string","null"],"description":"Additional CSS class applied to the sub-status badge, from its style metadata. Null when not set.","example":"substatus-meeting"},"comment":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether a comment is required when assigning this sub-status,\nnormalized from the sub-status metadata to an integer flag\n(0 = not required, 1 = required).\n","example":0},"action":{"type":["string","null"],"description":"Optional action keyword associated with the sub-status, from its metadata. Null when none.","example":null},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp of the sub-status, in ISO 8601 format. Null when not deleted.","example":null}}}}}}}},"TempusCorrectionApproval":{"type":"object","description":"A single approval (validation) decision attached to a Tempus time-point\ncorrection request, as serialized by the V1 `CorrectionApprovalResource`.\n\nWhen an employee submits a correction to their recorded time points, one or\nmore validators are asked to approve or reject it. Each `TempusCorrectionApproval`\nrecords the decision of one validator for one correction. The `status` field\ncarries the current decision state (pending until the validator acts).\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Several keys are renamed from their underlying columns:\n`mxvp_user_id` maps to the tenant (`pbx_id`), `ext_id` maps to the validating\nemployee (`validator_id`), and `comment` maps to the stored `note`. The\n`validator` object is only present when the validator relation is eager-loaded\non the model; it is absent (key omitted) otherwise.\n","required":["id","mxvp_user_id","correction_id","ext_id","status","comment","create_time"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of this approval record.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this approval. Sourced from the\nmodel `pbx_id` column.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"correction_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus time-point correction request this approval\ndecision belongs to.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"ext_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee acting as the validator for this\ncorrection. Sourced from the model `validator_id` column.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"validator":{"type":"object","description":"Summary of the validating employee. Only present when the `validator`\nrelation is eager-loaded on the model; the key is omitted when the relation\nis not loaded. The `name` falls back to the linked user's name when the\nemployee record has no own name.\n","properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the validating employee.","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Display name of the validating employee.","example":"Jane Smith"}}},"status":{"type":"string","enum":["pending","accepted","rejected"],"description":"Current decision state of this approval. `pending` means the validator has\nnot yet acted, `accepted` means the correction was approved, and `rejected`\nmeans it was declined.\n","example":"pending"},"comment":{"type":["string","null"],"description":"Free-form note left by the validator explaining the decision. Sourced from\nthe model `note` column. Null when no note was provided.\n","example":"Approved after confirming the corrected clock-in time with the team lead."},"create_time":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp of when this approval record was created. Null if the\ncreation timestamp is unavailable.\n","example":"2024-03-01T08:29:07+00:00","readOnly":true}}},"TempusCorrectionList":{"type":"object","description":"A Tempus time point correction as serialized by the V1 `CorrectionListResource`.\nA correction is a request to change, add, or remove an employee's recorded\nattendance time point (for example fixing a missed clock-in, adjusting a start\ntime, or changing the recorded status). Each correction belongs to exactly one\nPbx (tenant), references the employee who requested it, and once accepted is\napplied to the underlying time point.\n\nA correction captures both the original (\"old\") and the requested (\"new\")\nvalues for the affected time point: its timestamp, status, and sub-status. When\n`timepoint_id` is null the correction requests creating a brand-new time point;\nwhen `new_time` is null the correction requests removing the referenced time\npoint.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The status workflow fields `accepted_by`,\n`accepted_validations_count`, and `refused_validations_count`, and the\n`deleted_at` soft-delete timestamp, exist on the model but are not exposed by\nthis resource.\n\nThe `requesterExt`, `newStatus`, and `oldStatus` properties are optional\nexpansions: they are present only when explicitly requested through the\n`include` query parameter (for example `?include=requesterExt,newStatus,oldStatus`)\nand the corresponding relation could be resolved. When omitted from the\n`include` list they are absent from the response entirely.\n","required":["id","mxvp_user_id","timepoint_id","requester_ext_id","new_status_id","new_sub_status_id","old_status_id","old_sub_status_id","new_time","old_time","correction_comment","new_comment","status","create_time","update_time"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique correction identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this correction. Exposed under the\nlegacy field name `mxvp_user_id`; it maps to the model's `pbx_id` column.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"timepoint_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the existing time point this correction targets. Null when the\ncorrection requests creating a new time point rather than amending an\nexisting one.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"requester_ext_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus employee who requested the correction (the model's\n`employee_id`). When the `requester` relation is loaded its id is used;\notherwise the stored `employee_id` is returned. Null when no requesting\nemployee is recorded.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"new_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status requested for the corrected time point.\nReferences a `TempusStatus` record. Null when the correction does not change\nthe status.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"new_sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus sub-status requested for the corrected time point.\nReferences a `TempusSubStatus` record. Null when no sub-status change is\nrequested.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"old_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status that was recorded on the time point before\nthe correction. References a `TempusStatus` record. Null when no prior\nstatus applies.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"old_sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus sub-status that was recorded on the time point\nbefore the correction. References a `TempusSubStatus` record. Null when no\nprior sub-status applies.\n","example":"550e8400-e29b-41d4-a716-446655440007"},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Location the correction asks the time point to be recorded at. Null when the\ncorrection does not touch the location, which is NOT the same as asking for\nthe location to be cleared: acceptance leaves the current one as it is.\nAlways null on corrections raised before this field existed.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"old_location_id":{"type":["string","null"],"format":"uuid","description":"The location the time point was pointed at when the correction was raised.\nA snapshot, so the requested move reads as old -> new.\n","example":"550e8400-e29b-41d4-a716-446655440011"},"new_time":{"type":["string","null"],"format":"date-time","description":"Requested timestamp for the corrected time point, in ISO 8601 form. Null\nwhen the correction requests removing the referenced time point rather than\nchanging its time.\n","example":"2024-03-01T08:29:07Z"},"old_time":{"type":["string","null"],"format":"date-time","description":"Original timestamp of the time point before the correction, in ISO 8601\nform. Null when there was no prior recorded time (for example an add\nrequest).\n","example":"2024-03-01T08:00:00Z"},"correction_comment":{"type":["string","null"],"description":"Free-form justification entered by the requester explaining why the\ncorrection is needed. Null when no comment was provided.\n","example":"Forgot to clock in after lunch break."},"new_comment":{"type":["string","null"],"description":"Comment to apply to the corrected (or newly created) time point. Null when\nno comment is supplied.\n","example":"Corrected start time per manager approval."},"status":{"type":["string","null"],"enum":["pending","accepted","rejected","canceled","rejected_closed"],"description":"Lifecycle state of the correction request. `pending` awaits validator\napproval; `accepted` has been applied to the time point; `rejected` was\ndeclined; `canceled` was withdrawn; `rejected_closed` was declined and the\nrequest is closed. Legacy stored values `refused` and `refused_closed` are\nnormalised to `rejected` and `rejected_closed` respectively. Null when no\nstatus is set.\n","example":"pending"},"create_time":{"type":"string","format":"date-time","description":"Timestamp when the correction was created, in ISO 8601 form.","example":"2024-03-01T08:29:07Z","readOnly":true},"update_time":{"type":"string","format":"date-time","description":"Timestamp when the correction was last updated, in ISO 8601 form.","example":"2024-03-01T09:15:42Z","readOnly":true},"requesterExt":{"type":["object","null"],"description":"Summary of the requesting employee's extension. Optional expansion: present\nonly when `requesterExt` is passed in the `include` query parameter and the\n`requester` relation resolves. Null when requested but the requester cannot\nbe resolved.\n","properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the requesting Tempus employee.","example":"550e8400-e29b-41d4-a716-446655440003"},"number":{"type":["string","null"],"description":"Primary extension number of the requester's linked user. Null when the\nuser has no extension assigned.\n","example":"1042"},"name":{"type":["string","null"],"description":"First name of the requesting employee.","example":"Jane"},"name2":{"type":["string","null"],"description":"Last name of the requesting employee.","example":"Smith"}}},"newStatus":{"type":["object","null"],"description":"Full details of the requested (\"new\") Tempus status. Optional expansion:\npresent only when `newStatus` is passed in the `include` query parameter and\nthe `newStatus` relation resolves. Null when requested but unresolved.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440004"},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the status (maps to the model's\n`pbx_id`).\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the status.","example":"Working"},"icon":{"type":["string","null"],"description":"CSS icon class used to represent the status in the UI. Null when no icon\nis configured.\n","example":"la la-briefcase"},"fontcolor":{"type":["string","null"],"description":"Foreground (font) colour for the status badge. Null when unset.","example":"#ffffff"},"backgroundcolor":{"type":["string","null"],"description":"Background colour for the status badge. Null when unset.","example":"#2e7d32"},"css":{"type":["string","null"],"description":"Additional CSS class applied to the status badge. Null when unset.","example":"status-working"},"comment":{"type":"boolean","description":"Whether a comment is required when applying this status. Defaults to\nfalse.\n","example":false},"payable":{"type":"boolean","description":"Whether time spent in this status counts as payable working time.","example":true},"action":{"type":["string","null"],"description":"Optional workflow action associated with the status (stored in the\nstatus meta data). Null when none is configured.\n","example":"clock_in"},"migration_id":{"type":["string","null"],"description":"Identifier carried over from a legacy migration of this status. Null when\nthe status was not migrated.\n","example":"12345"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp of the status, in ISO 8601 form. Null when the\nstatus is active (not deleted).\n","example":null}}},"oldStatus":{"type":["object","null"],"description":"Full details of the previously recorded (\"old\") Tempus status, using the\nsame shape as `newStatus`. Optional expansion: present only when `oldStatus`\nis passed in the `include` query parameter and the `oldStatus` relation\nresolves. Null when requested but unresolved.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440006"},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the status (maps to the model's\n`pbx_id`).\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the status.","example":"Break"},"icon":{"type":["string","null"],"description":"CSS icon class used to represent the status in the UI. Null when unset.","example":"la la-coffee"},"fontcolor":{"type":["string","null"],"description":"Foreground (font) colour for the status badge. Null when unset.","example":"#000000"},"backgroundcolor":{"type":["string","null"],"description":"Background colour for the status badge. Null when unset.","example":"#fbc02d"},"css":{"type":["string","null"],"description":"Additional CSS class applied to the status badge. Null when unset.","example":"status-break"},"comment":{"type":"boolean","description":"Whether a comment is required when applying this status. Defaults to false.","example":false},"payable":{"type":"boolean","description":"Whether time spent in this status counts as payable working time.","example":false},"action":{"type":["string","null"],"description":"Optional workflow action associated with the status (stored in the\nstatus meta data). Null when none is configured.\n","example":null},"migration_id":{"type":["string","null"],"description":"Identifier carried over from a legacy migration of this status. Null when\nthe status was not migrated.\n","example":null},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp of the status, in ISO 8601 form. Null when the\nstatus is active (not deleted).\n","example":null}}}}},"TempusPendingCorrection":{"type":"object","description":"A pending Tempus time-point correction request as serialized by the V1\n`PendingCorrectionResource`. These are change requests raised by an employee\n(or on their behalf) to add, modify, or remove a time-point (clock event) on\ntheir attendance sheet, awaiting validation by an authorized approver.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Several fields are derived: `requested_ext_id` and\n`full_name` are resolved from the related employee, `date` is the formatted\ncreation date, and the date\/time fields are reformatted from the model's\n`new_time` and `old_time` timestamps. The status objects (`old_status`,\n`new_status`, `old_sub_status`, `new_sub_status`) are populated only when the\ncorresponding relationship is loaded on the model; when a relation is not\nloaded, or no status is set, the field is null.\n\nA correction may have no \"old\" side (for example when it requests adding a\nbrand-new time-point): in that case `old_status`, `old_sub_status`,\n`old_datetime`, and `old_time` are all null.\n","required":["id","requested_ext_id","full_name","date","timepoint_id","old_status","new_status","old_sub_status","new_sub_status","new_datetime","old_datetime","new_time","old_time","correction_comment","new_status_id","new_comment"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the correction request.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"requested_ext_id":{"type":["string","null"],"description":"Telephony extension number of the employee who is the subject of this\ncorrection, resolved from the linked employee record. Null when the\nemployee has no associated extension.\n","example":"1042"},"full_name":{"type":"string","description":"Display name of the employee the correction applies to, taken from the\nemployee's full name when available, otherwise assembled from their first\nand last name. May be an empty string when no name is on file.\n","example":"Jane Smith"},"date":{"type":["string","null"],"description":"Human-readable creation date of the correction request, formatted as\n\"Day YYYY-MM-DD\" (the abbreviated weekday followed by the ISO date). Null\nwhen no creation timestamp is set.\n","example":"Mon 2024-03-04"},"timepoint_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the existing time-point this correction modifies or removes.\nNull when the correction requests adding a new time-point that does not\nyet exist.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"old_status":{"type":["object","null"],"description":"The time-point's status before the correction, including its display\nstyling. Null when there is no prior status (for example an add request)\nor when the `oldStatus` relation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","description":"Display name of the status.","example":"Working"},"font_color":{"type":"string","description":"CSS font color used to render the status label. Empty string when no\ncolor is configured.\n","example":"#ffffff"},"background_color":{"type":"string","description":"CSS background color used to render the status badge. Empty string\nwhen no color is configured.\n","example":"#2e7d32"},"icon":{"type":"string","description":"CSS icon class used to render the status icon. Empty string when no\nicon is configured.\n","example":"la la-briefcase"}}},"new_status":{"type":["object","null"],"description":"The time-point's requested status after the correction, including its\ndisplay styling. Null when no new status is requested or when the\n`newStatus` relation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440021"},"name":{"type":"string","description":"Display name of the status.","example":"Home Office"},"font_color":{"type":"string","description":"CSS font color used to render the status label. Empty string when no\ncolor is configured.\n","example":"#ffffff"},"background_color":{"type":"string","description":"CSS background color used to render the status badge. Empty string\nwhen no color is configured.\n","example":"#1565c0"},"icon":{"type":"string","description":"CSS icon class used to render the status icon. Empty string when no\nicon is configured.\n","example":"la la-home"}}},"old_sub_status":{"type":["object","null"],"description":"The time-point's sub-status before the correction, including its display\nstyling. Null when there is no prior sub-status or when the `oldSubStatus`\nrelation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440022"},"name":{"type":"string","description":"Display name of the sub-status.","example":"Meeting"},"font_color":{"type":"string","description":"CSS font color used to render the sub-status label. Empty string when\nno color is configured.\n","example":"#000000"},"background_color":{"type":"string","description":"CSS background color used to render the sub-status badge. Empty string\nwhen no color is configured.\n","example":"#fff59d"},"icon":{"type":"string","description":"CSS icon class used to render the sub-status icon. Empty string when\nno icon is configured.\n","example":"la la-users"}}},"new_sub_status":{"type":["object","null"],"description":"The time-point's requested sub-status after the correction, including its\ndisplay styling. Null when no new sub-status is requested or when the\n`newSubStatus` relation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440023"},"name":{"type":"string","description":"Display name of the sub-status.","example":"Training"},"font_color":{"type":"string","description":"CSS font color used to render the sub-status label. Empty string when\nno color is configured.\n","example":"#000000"},"background_color":{"type":"string","description":"CSS background color used to render the sub-status badge. Empty string\nwhen no color is configured.\n","example":"#b2dfdb"},"icon":{"type":"string","description":"CSS icon class used to render the sub-status icon. Empty string when\nno icon is configured.\n","example":"la la-graduation-cap"}}},"old_location":{"type":["object","null"],"description":"The location the time point was pointed at when the correction was raised.\nNull when it had none, or when the `oldLocation` relation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440011"},"name":{"type":"string","example":"HQ Luxembourg"},"latitude":{"type":["number","null"],"format":"double","example":49.6008},"longitude":{"type":["number","null"],"format":"double","example":6.133},"geofence_radius_m":{"type":["integer","null"],"example":150}}},"new_location":{"type":["object","null"],"description":"The location the correction asks the time point to be recorded at. Null\nwhen the correction does not touch the location, which is NOT the same as\nasking for it to be cleared: accepting leaves the current location as is.\n","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","example":"Remote office"},"latitude":{"type":["number","null"],"format":"double","example":49.612},"longitude":{"type":["number","null"],"format":"double","example":6.13},"geofence_radius_m":{"type":["integer","null"],"example":200}}},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Raw identifier behind `new_location`. Null when the correction does not\ntouch the location.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"old_location_id":{"type":["string","null"],"format":"uuid","description":"Raw identifier behind `old_location`.","example":"550e8400-e29b-41d4-a716-446655440011"},"new_datetime":{"type":["string","null"],"description":"Requested new time-point timestamp, formatted as \"YYYY-MM-DD HH:MM:SS\"\n(local PBX time). Null when no new time is requested (for example a\nremoval request).\n","example":"2024-03-04 09:00:00"},"old_datetime":{"type":["string","null"],"description":"Original time-point timestamp before the correction, formatted as\n\"YYYY-MM-DD HH:MM:SS\" (local PBX time). Null when there is no prior status\n(for example an add request) or when no original time is set.\n","example":"2024-03-04 08:30:00"},"new_time":{"type":["string","null"],"description":"Requested new clock time only, formatted as \"HH:MM\" (local PBX time). Null\nwhen no new time is requested.\n","example":"09:00"},"old_time":{"type":["string","null"],"description":"Original clock time only before the correction, formatted as \"HH:MM\"\n(local PBX time). Null when there is no prior status or no original time.\n","example":"08:30"},"correction_comment":{"type":["string","null"],"description":"Free-form justification provided by the requester explaining why the\ncorrection is needed. Null when no comment was supplied.\n","example":"Forgot to clock in after lunch"},"new_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the requested new status. Null when the correction does not\nchange the status. This is the raw foreign key; the resolved status object\nis exposed under `new_status`.\n","example":"550e8400-e29b-41d4-a716-446655440021"},"new_comment":{"type":["string","null"],"description":"Comment to be stored on the time-point itself once the correction is\napplied (distinct from `correction_comment`, which justifies the request).\nNull when no time-point comment is supplied.\n","example":"Client visit on site"}}},"TempusPendingCorrectionDetails":{"type":"object","description":"Compact summary of a single Tempus time point (clock event) that is awaiting\nmanual correction by a validator, as serialized by the V1\n`PendingCorrectionDetailsResource`. It surfaces just enough context for a\nreviewer to identify the event in a pending-corrections list: when it occurred\n(split into a calendar date and a wall-clock time) and the presentation status\nit carries.\n\nThe underlying `start_time` of the time point is a single timestamp; this\nresource deliberately splits it into separate `date` and `time` strings (both\nderived from the same moment) rather than returning a combined date-time value.\n\nThe nested `status` object describes the Tempus status assigned to the time\npoint along with the styling hints (colours and icon) the UI uses to render it.\nWhen the time point has no associated status, the status fields fall back to\nnull identifiers and empty-string styling values.\n","required":["id","date","time","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the time point awaiting correction.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"date":{"type":["string","null"],"format":"date","description":"Calendar date of the time point's start, formatted as `YYYY-MM-DD`.\nNull when the time point has no recorded start time.\n","example":"2024-03-01"},"time":{"type":["string","null"],"description":"Wall-clock time of the time point's start, formatted as `HH:MM:SS`\n(24-hour). Null when the time point has no recorded start time.\n","example":"08:29:07"},"status":{"type":"object","description":"The Tempus status assigned to this time point, together with the styling\nhints used to render it. Always present as an object; its `id` and `name`\nare null and the styling values are empty strings when no status is linked\nto the time point.\n","required":["id","name","font_color","background_color","icon"],"properties":{"id":{"type":["string","null"],"format":"uuid","description":"Unique identifier of the linked Tempus status, or null when the time\npoint has no associated status.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Human-readable name of the status (for example a work, break, or\nabsence label). Null when no status is linked.\n","example":"Working"},"font_color":{"type":"string","description":"Foreground (text) colour used to render the status, as a CSS colour\nvalue (typically a hex code). Empty string when no styling is defined.\n","example":"#FFFFFF"},"background_color":{"type":"string","description":"Background colour used to render the status, as a CSS colour value\n(typically a hex code). Empty string when no styling is defined.\n","example":"#2E7D32"},"icon":{"type":"string","description":"Icon CSS class used to represent the status in the UI. Empty string\nwhen no styling is defined.\n","example":"la la-briefcase"}}}}},"TempusTimePoint":{"type":"object","description":"A Tempus time point as serialized by the V1 `TimePointResource`. A time point\nrecords a single interval during which an employee was in a given presence or\nattendance status (for example working, on break, or off). Each time point\nbelongs to exactly one Pbx (tenant) and one user, references the status that\nwas active during the interval, and is bounded by a `start_time` and an\noptional `end_time`.\n\nAn open time point (one with `end_time` set to null) represents the employee's\ncurrent, ongoing status. When a new time point is opened for an employee, any\npreviously open time point for that same employee is automatically closed by\nsetting its `end_time`.\n\nThis object documents the exact keys returned by the resource, not every raw\ndatabase column. Columns such as `successive_count`, `comment`, `mapping_id`,\n`deleted_at`, `created_by`, and `updated_by` exist on the model but are not\nexposed by this resource. The `sources`, `triggers`, and `meta_data` fields\nare stored as JSON and returned as free-form objects.\n\nLocation data comes in three distinct parts that must not be conflated:\n`location_id` plus the nested `location` object describe the *configured*\nlocation record the employee selected; `device_gps` records where the\n*device* said it was; `location_check` is the comparison of the two.\n","required":["id","pbx_id","user_id","status_id","start_time","is_synced"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique time point identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this time point.","example":"550e8400-e29b-41d4-a716-446655440001"},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user (employee) this time point belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"status_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus status that was active during this interval (for\nexample working, break, or off). References a `TempusStatus` record.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"location_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the location the status was recorded against. Null when no\nlocation was selected.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"location":{"type":["object","null"],"description":"The configured location record referenced by `location_id`, including its\nown coordinates and geofence radius. Null when `location_id` is null.\nThese are the location's *configured* coordinates, not the device's: see\n`device_gps` for the latter.\n","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","example":"HQ Luxembourg"},"description":{"type":["string","null"],"example":null},"street_no":{"type":["string","null"],"example":"12"},"street":{"type":["string","null"],"example":"Rue de Bonnevoie"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"example":"1260"},"country_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440011"},"latitude":{"type":["number","null"],"format":"double","description":"The location's configured latitude, in degrees.","example":49.6008},"longitude":{"type":["number","null"],"format":"double","description":"The location's configured longitude, in degrees.","example":6.133},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the configured point, in metres.","example":150},"is_fixed_location":{"type":"boolean","example":true}}},"start_time":{"type":"string","format":"date-time","description":"Timestamp marking the beginning of the status interval.","example":"2024-03-01T08:29:07Z"},"end_time":{"type":["string","null"],"format":"date-time","description":"Timestamp marking the end of the status interval. Null while the time\npoint is still open, which indicates the employee's current ongoing\nstatus.\n","example":"2024-03-01T12:00:00Z"},"sources":{"type":["object","null"],"description":"Free-form JSON object describing the origin systems that contributed to\nthis time point (for example the cockpit UI, a badge reader, or an API\nclient). Structure varies by integration. Null when no source data is\nrecorded.\n","additionalProperties":true,"example":{"channel":"cockpit","device_id":"550e8400-e29b-41d4-a716-446655440010"}},"triggers":{"type":["object","null"],"description":"Free-form JSON object describing the events that triggered the creation or\nclosing of this time point (for example a manual status change or an\nautomated rollover). Structure varies by integration. Null when no trigger\ndata is recorded.\n","additionalProperties":true,"example":{"type":"manual_change","actor_id":"550e8400-e29b-41d4-a716-446655440002"}},"meta_data":{"type":["object","null"],"description":"Free-form JSON object holding additional key-value metadata attached to\nthe time point, exactly as the client sent it. Keys are\nintegration-specific. Null when no metadata is stored.\n\nTwo keys are written by the server rather than the client: `device_gps`\nand `location_check`, both also surfaced as top-level fields of this\nresource (see below).\n","additionalProperties":true,"example":{"note":"Started shift remotely","gpsLat":49.95,"gpsLong":6.133}},"device_gps":{"type":["object","null"],"description":"The coordinates the client reported when this status was recorded, stored\nexactly as sent. Read from whichever field the client already uses\n(`gpsData`, or GPS keys inside `meta_data`, under any of the historical\nspellings such as `gpsLat` \/ `lat` \/ `latitude`).\n\nThis is never derived from, corrected by, or overwritten with the\ncoordinates configured on the selected location: it records where the\ndevice claimed to be, which is only useful as evidence if it is left\nuntouched. Compare it with `location.latitude` \/ `location.longitude`,\nwhich describe the configured location record instead.\n\nNull when the request carried no usable fix (no coordinates at all, only\none of the pair, or values outside the valid latitude \/ longitude range).\nA request with an unusable fix still succeeds, and whatever it sent is\npreserved verbatim under `meta_data`.\n","required":["latitude","longitude"],"properties":{"latitude":{"type":"number","format":"double","description":"Latitude reported by the device, in degrees.","example":49.95},"longitude":{"type":"number","format":"double","description":"Longitude reported by the device, in degrees.","example":6.133},"accuracy_m":{"type":["number","null"],"format":"double","description":"Accuracy radius of the fix in metres, as reported by the device. Null\nwhen the client sent none. Used as tolerance by `location_check`.\n","example":12.5},"captured_at":{"type":["string","null"],"format":"date-time","description":"The device's GPS timestamp, parsed. Null when the client sent none or\nsent a value that could not be parsed.\n","example":"2026-07-07T10:07:39+00:00"},"captured_at_raw":{"type":["string","number","null"],"description":"The GPS timestamp exactly as the client sent it: epoch milliseconds,\nepoch seconds, or an ISO 8601 string. Kept alongside the parsed value\nso nothing the client reported is lost.\n","example":1783418859289}},"example":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289}},"location_check":{"type":["object","null"],"description":"Comparison of `device_gps` against the selected location's configured\ncoordinates and geofence radius. This is the integrity signal: it shows\nwhen an employee recorded a status against a location they were not\nactually at.\n\nNull when the time point has neither a device fix nor a location, and on\ntime points written before this check existed.\n","properties":{"location_id":{"type":["string","null"],"format":"uuid","description":"The location the status was recorded against, if any.","example":"550e8400-e29b-41d4-a716-446655440010"},"location_latitude":{"type":["number","null"],"format":"double","description":"The location's configured latitude at the time of the check.","example":49.6008},"location_longitude":{"type":["number","null"],"format":"double","description":"The location's configured longitude at the time of the check.","example":6.133},"geofence_radius_m":{"type":["integer","null"],"description":"The location's configured geofence radius in metres.","example":150},"distance_m":{"type":["integer","null"],"description":"Distance in metres between the device fix and the location's\nconfigured point. Recorded whenever both sides have coordinates, even\nwhen the location has no geofence radius and no in-or-out verdict is\npossible: the distance alone is the useful signal.\n","example":38957},"within_geofence":{"type":["boolean","null"],"description":"Whether the device fix falls inside the geofence. The device's own\nreported accuracy is added to the radius as tolerance, so a poor fix\nslightly outside a small geofence is not treated as a discrepancy.\nNull when no verdict was possible.\n","example":false},"verdict":{"type":"string","enum":["match","mismatch","unknown"],"description":"`match`: the device fix is inside the geofence.\n`mismatch`: the device fix is outside it, meaning the selected\nlocation disagrees with where the device said it was.\n`unknown`: not enough data to judge, see `reason`.\n","example":"mismatch"},"reason":{"type":["string","null"],"enum":["no_device_gps","no_location","location_without_coordinates","no_geofence_radius",null],"description":"Why the verdict is `unknown`. `no_device_gps`: the request carried no\nusable fix. `no_location`: no location was selected, or it does not\nbelong to this tenant. `location_without_coordinates`: the location\nrecord has no coordinates configured. `no_geofence_radius`: the\nlocation has coordinates but no radius, so only `distance_m` is\nmeaningful. Null when the verdict is `match` or `mismatch`.\n","example":null}},"example":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null}},"is_synced":{"type":"boolean","description":"Whether this time point has been synchronized to the downstream\ntime-and-attendance system. False until the record has been exported.\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the time point was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the time point was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}},"TempusUserTimepointLegacy":{"type":"object","description":"A single Tempus time point (clock event) serialized in the legacy mobile-app\nformat by the V1 `UserTimepointLegacyResource`. A time point records when an\nemployee entered a given attendance status (for example \"Working\", \"Break\" or\n\"Off\"), optionally with a captured GPS location and a free-text comment.\n\nThis object documents the exact keys returned by the resource, not the raw\n`tempus_time_points` columns. The `status` and `substatus` objects are\nflattened presentation views assembled from the related `TempusStatus` and\n`TempusSubStatus` records (their display style is read from each status's\n`style` JSON and its comment requirement from its `meta_data` JSON). The\n`gpsLong`, `gpsLat` and `gpsTimestamp` values are extracted from the time\npoint's own `meta_data` JSON, tolerating several historical key spellings, and\nfalling back to the normalised `device_gps` block for time points recorded\nsince that block existed.\n\nThe GPS fields (`gpsLong` \/ `gpsLat` \/ `gpsTimestamp` \/ `device_gps`) describe\nwhere the *device* said it was. The nested `location` object describes the\n*configured* location record the employee selected. `location_check` compares\nthe two. The three are independent and must not be conflated.\n\nSeveral boolean-like flags (`status.comment`, `status.payable`,\n`substatus.comment`) are returned as the integers `1` or `0` rather than JSON\nbooleans, preserving compatibility with the legacy client.\n","required":["id","ext_id","time","status","comment","gpsLong","gpsLat","gpsTimestamp","substatus"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the time point (clock event).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"ext_id":{"type":["string","null"],"description":"External employee identifier resolved from the `employee_id` route\nparameter, used by the legacy client to correlate the event with its own\nemployee record. Null when no external mapping exists for the employee.\n","example":"EMP-10472"},"time":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp marking when this status began (the time point's\n`start_time`). Null only when no start time is recorded.\n","example":"2024-03-01T08:29:07Z"},"status":{"type":"object","description":"The primary attendance status active from `time`, flattened from the\nrelated `TempusStatus` record together with its display style.\n","required":["id","name","icon","fontcolor","backgroundcolor","css","comment","payable"],"properties":{"id":{"type":["string","null"],"format":"uuid","description":"Identifier of the status. Null if the status is unavailable.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Human-readable status name shown to the employee.","example":"Working"},"icon":{"type":["string","null"],"description":"CSS icon class used to render the status (from the status style's\n`icon_class`). Null when no icon is configured.\n","example":"la la-briefcase"},"fontcolor":{"type":["string","null"],"description":"Foreground (text) colour for the status label, as a CSS colour value\n(from the status style's `font_color`). Null when unset.\n","example":"#ffffff"},"backgroundcolor":{"type":["string","null"],"description":"Background colour for the status label, as a CSS colour value (from\nthe status style's `bg_color`). Null when unset.\n","example":"#2e7d32"},"css":{"type":"string","description":"Additional CSS class string for the status (from the style's `css`,\nfalling back to `css_class`). Empty string when none is configured.\n","example":"status-working"},"comment":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether a comment is required when selecting this status: 1 if\nrequired, 0 otherwise. Derived from the status `meta_data`\n(`comment_required` flag or a `comment` entry in its `flags` list).\n","example":0},"payable":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether time spent in this status is payable working time: 1 if\npayable, 0 otherwise.\n","example":1}}},"comment":{"type":["string","null"],"description":"Free-text comment attached to this time point. Falls back to the\n`comment` key inside the time point's `meta_data` when no dedicated\ncomment column value is present. Null when no comment was recorded.\n","example":"Started shift on site"},"gpsLong":{"type":["number","string","null"],"description":"Longitude of the captured GPS location, read from the time point's\n`meta_data` (accepting the `gpsLong`, `gps_long`, `longitude` or `lng`\nkeys). The stored value may be a number or a string. Null when no\nlocation was captured.\n","example":-73.9857},"gpsLat":{"type":["number","string","null"],"description":"Latitude of the captured GPS location, read from the time point's\n`meta_data` (accepting the `gpsLat`, `gps_lat`, `latitude` or `lat`\nkeys). The stored value may be a number or a string. Null when no\nlocation was captured.\n","example":40.7484},"gpsTimestamp":{"type":["string","integer","null"],"description":"Timestamp at which the GPS location was captured, read from the time\npoint's `meta_data` (accepting the `gpsTimestamp`, `gps_timestamp`,\n`timestamp` or `gps_time` keys). May be an ISO 8601 string or a Unix\nepoch value depending on the originating client. Null when no location\nwas captured.\n","example":"2024-03-01T08:29:05Z"},"device_gps":{"type":["object","null"],"description":"The coordinates the client reported, stored exactly as sent and never\nreplaced by the coordinates configured on the selected location. This is\nthe same fix the flat `gpsLat` \/ `gpsLong` \/ `gpsTimestamp` fields expose,\nin a normalised and typed form (a parsed timestamp, plus the reported\naccuracy, which the flat fields have no place for). Null when the time\npoint carried no usable fix.\n","properties":{"latitude":{"type":"number","format":"double","example":49.95},"longitude":{"type":"number","format":"double","example":6.133},"accuracy_m":{"type":["number","null"],"format":"double","description":"Accuracy radius of the fix in metres, as reported by the device.","example":12.5},"captured_at":{"type":["string","null"],"format":"date-time","description":"The device's GPS timestamp, parsed. Null when unparseable or absent.","example":"2026-07-07T10:07:39+00:00"},"captured_at_raw":{"type":["string","number","null"],"description":"The GPS timestamp exactly as the client sent it.","example":1783418859289}}},"location_check":{"type":["object","null"],"description":"Comparison of `device_gps` against the selected location's configured\ncoordinates and geofence radius: the signal that a status was recorded\nagainst a location the employee was not actually at. Same shape and\nsemantics as on the `TempusTimePoint` model. Null when the time point has\nneither a device fix nor a location, and on time points written before\nthis check existed.\n","properties":{"location_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"location_latitude":{"type":["number","null"],"format":"double","example":49.6008},"location_longitude":{"type":["number","null"],"format":"double","example":6.133},"geofence_radius_m":{"type":["integer","null"],"example":150},"distance_m":{"type":["integer","null"],"description":"Metres between the device fix and the location's configured point.\nRecorded whenever both have coordinates, even with no radius set.\n","example":38957},"within_geofence":{"type":["boolean","null"],"description":"Whether the fix falls inside the geofence, with the device's own\nreported accuracy allowed as tolerance. Null when no verdict was\npossible.\n","example":false},"verdict":{"type":"string","enum":["match","mismatch","unknown"],"example":"mismatch"},"reason":{"type":["string","null"],"enum":["no_device_gps","no_location","location_without_coordinates","no_geofence_radius",null],"description":"Why the verdict is `unknown`. Null otherwise.","example":null}}},"substatus":{"type":["object","null"],"description":"The first associated sub-status for this time point (a refinement of the\nmain status, for example a specific break type), flattened from the\nrelated `TempusSubStatus` record together with its display style. Null\nwhen no sub-status is attached.\n","required":["id","name","icon","fontcolor","backgroundcolor","css","comment"],"properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":["string","null"],"description":"Human-readable sub-status name.","example":"Lunch break"},"icon":{"type":["string","null"],"description":"CSS icon class used to render the sub-status (from its style's\n`icon_class`). Null when no icon is configured.\n","example":"la la-coffee"},"fontcolor":{"type":["string","null"],"description":"Foreground (text) colour for the sub-status label, as a CSS colour\nvalue (from its style's `font_color`). Null when unset.\n","example":"#000000"},"backgroundcolor":{"type":["string","null"],"description":"Background colour for the sub-status label, as a CSS colour value\n(from its style's `bg_color`). Null when unset.\n","example":"#fff3e0"},"css":{"type":"string","description":"Additional CSS class string for the sub-status (from its style's\n`css`, falling back to `css_class`). Empty string when none is\nconfigured.\n","example":"substatus-lunch"},"comment":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether a comment is required when selecting this sub-status: 1 if\nrequired, 0 otherwise. Derived from the sub-status `meta_data`.\n","example":0}}}}},"TempusDepartment":{"type":"object","description":"Tempus department as serialized by the V1 `TempusDepartmentResource`.\nDepartments are a per-tenant (Pbx) catalog of organizational units used by\nthe Tempus time and attendance module. An employee's company context comes\nfrom their contract; a department is referenced by contracts and may be\nadopted by one or more companies within the tenant.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The `mxvp_user_id` key carries the owning Pbx (tenant)\nidentifier. The `flags` and `absence_validation_amount_required` keys are\nfixed compatibility fields emitted with constant values by the current API\nversion (an empty string and `0` respectively) and do not vary per record.\n","required":["id","mxvp_user_id","name","flags","absence_validation_amount_required","timestamp","delete_date"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique department identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns this department (the model's\n`pbx_id`). Null for departments that are not bound to a specific tenant.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the department.","example":"Customer Support"},"flags":{"type":"string","description":"Reserved compatibility field. The current API version always emits an\nempty string. Integrators should not rely on this field carrying data.\n","example":""},"absence_validation_amount_required":{"type":"integer","format":"int32","description":"Reserved compatibility field indicating the number of absence\nvalidations required. The current API version always emits `0`.\n","example":0},"timestamp":{"type":["string","null"],"format":"date-time","description":"Timestamp when the department was last updated (the model's\n`updated_at`). Null when the record has never been persisted with a\ntimestamp.\n","example":"2024-03-01T08:29:07Z","readOnly":true},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp (the model's `deleted_at`). Null for active\ndepartments; set to the deletion time when the department has been\nsoft-deleted.\n","example":null,"readOnly":true}}},"TempusDepartmentBasic":{"type":"object","description":"Tempus department as serialized by the V1 `DepartmentResource`.\n\nDepartments are a per-tenant (Pbx) catalog of organizational units used by\nthe Tempus time and attendance module. An employee's company context comes\nfrom their contract; a department is referenced by contracts and may be\nadopted by one or more companies within the tenant.\n\nThis is the properly named representation returned by the `departments`\nendpoint. It exposes only the meaningful fields (id, name, description). The\nlegacy `groups` endpoint (schema `TempusDepartment`) returns the same records\nunder legacy key names and is kept for backward compatibility only.\n","required":["id","name","description"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique department identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"name":{"type":"string","description":"Display name of the department.","example":"Customer Support"},"description":{"type":["string","null"],"description":"Optional free-text description of the department.","example":"Handles inbound customer requests"}}},"TempusUser":{"type":"object","description":"Tempus user (time-and-attendance employee) as serialized by the V1\n`TempusUserResource`. Each record represents one `TempusEmployee` belonging to\na single Pbx (tenant) and is linked to an optional Voxbi `User` account, from\nwhich the email, name, and telephony extension are resolved.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Name fields fall back to the linked user's values when the\nemployee record itself does not carry them: `first_name`, `last_name`, and\n`full_name` are taken from the employee where set, otherwise from the linked\nuser. `email` and `ext_number` are always sourced from the linked user and its\nfirst extension, so they are null when no user (or no extension) is linked.\n\n`ext_id` is resolved through a helper: it is the identifier of the extension\nbelonging to the linked user when one exists, and otherwise falls back to the\nemployee's own identifier. It is therefore always a non-null string.\n\nThe `soop_*` fields are legacy placeholders carried over from the previous\ntime-tracking system (SOOP). They are currently always null and are returned\nonly for backward compatibility with older integrations.\n","required":["ext_id","pbx_id","ext_number","first_name","last_name","full_name","email","soop_enable","soop_name","soop_badge"],"properties":{"ext_id":{"type":"string","format":"uuid","description":"Identifier used to address this user on the telephony stack. Resolves to\nthe identifier of the extension owned by the linked Voxbi user when one\nexists; otherwise it falls back to the Tempus employee identifier. Always\npresent.\n","readOnly":true,"example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this Tempus employee.","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_number":{"type":["string","null"],"description":"Dialable extension number of the linked user's first extension. Null when\nthe employee has no linked user or that user has no extension.\n","example":"101"},"first_name":{"type":["string","null"],"description":"Given name of the employee. Taken from the employee record when set,\notherwise from the linked Voxbi user. Null when neither provides a value.\n","example":"Jane"},"last_name":{"type":["string","null"],"description":"Family name of the employee. Taken from the employee record when set,\notherwise from the linked Voxbi user. Null when neither provides a value.\n","example":"Smith"},"full_name":{"type":["string","null"],"description":"Computed display name of the employee. Derived from the employee's first\nand last name (ordered per the Pbx name-display preference), falling back\nto the linked user's name. Null when no name is available.\n","readOnly":true,"example":"Jane Smith"},"email":{"type":["string","null"],"format":"email","description":"Email address of the linked Voxbi user, used as that user's login\nidentifier. Null when the employee has no linked user.\n","example":"jane.smith@example.com"},"soop_enable":{"type":["integer","null"],"format":"int32","description":"Legacy SOOP badge-enabled flag (1 enabled, 0 disabled), retained for\nbackward compatibility. Currently always null.\n","example":null},"soop_name":{"type":["string","null"],"description":"Legacy SOOP badge name, retained for backward compatibility. Currently\nalways null.\n","example":null},"soop_badge":{"type":["string","null"],"description":"Legacy SOOP badge data (the encoded badge value), retained for backward\ncompatibility. Currently always null.\n","example":null}}},"TempusUserProfile":{"type":"object","description":"Tempus user profile for a single employee linked to a Voxbi Cockpit user: the\ncompany on their active contract, absence (holiday) balances, home office\nallowance, and overtime calculation period. It is assembled in memory by the\ncontroller (not a single Eloquent model), so the field set is fixed and\ndocumented below.\n\nDuration values in the absence summary and the overtime `compensatory_balance`\nare zero-padded `HH:MM:SS` strings where the hours component may exceed 24 (for\nexample \"120:00:00\") and may carry a leading minus sign for negative balances.\nHome office counters (`allowed`, `taken`, `remaining`) are integers in whole\ndays. Overtime accrual (`current_accrual.business` \/ `current_accrual.non_working`)\nis in seconds.\n\nThe optional feature blocks (`home_office`, `overtime`, `travel_time`) always\ncarry an `enabled` flag; their detail fields are present only when enabled.\n\n`travel_time_allowed` is a flat mirror of `travel_time.enabled`, kept for app\nclients that read the flag directly. Both are always present and always agree.\n\nThere are two validator-facing blocks, in opposite directions: `validator` is what\nthis employee may approve (null when they are not a validator), and `validators` is\nwho approves this employee (always an array, empty when nobody does).\n\nNote: when the requested employee has no active contract, the endpoint returns\nHTTP 422 with a `{ \"message\": ... }` body instead of this shape.\n","required":["employee","company","contract","absence","home_office","overtime","travel_time","travel_time_allowed","preferences","validator","validators"],"properties":{"employee":{"type":"object","description":"Basic identity details of the linked Tempus employee.","required":["full_name","email"],"properties":{"full_name":{"type":"string","description":"Full name of the employee, falling back to the linked user's name.","example":"Jane Smith"},"email":{"type":"string","format":"email","description":"Email address of the linked user account.","example":"jane.smith@example.com"}}},"company":{"type":"object","description":"The company on the employee's active contract.","required":["id","name"],"properties":{"id":{"type":["string","null"],"format":"uuid","description":"Identifier of the company. Null when the contract has no company.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Display name of the company. Null when the contract has no company.","example":"Acme Corp"}}},"contract":{"type":"object","description":"The employee's active employment contract dates.","required":["start","end"],"properties":{"start":{"type":["string","null"],"format":"date","description":"Start date of the active contract (a date, no time component).","example":"2024-01-01"},"end":{"type":["string","null"],"format":"date","description":"End date of the active contract; null for an open-ended contract.","example":null},"department_id":{"type":["string","null"],"format":"uuid","description":"UUID of the department on the active contract, or null when none is set.","example":"550e8400-e29b-41d4-a716-446655440042"}}},"absence":{"type":"object","description":"Holiday and absence balances for the current calendar year, each an `HH:MM:SS` duration string. Always present.","required":["possible","taken","remaining"],"properties":{"possible":{"type":"string","description":"Total holiday entitlement available for the year.","example":"200:00:00"},"taken":{"type":"string","description":"Holiday already consumed during the year.","example":"80:00:00"},"remaining":{"type":"string","description":"Holiday still available to take.","example":"120:00:00"}}},"home_office":{"type":"object","description":"Home office allowance for the current year. `allowed`, `taken` and\n`remaining` (whole days) are present only when `enabled` is true.\n","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether home office is enabled for the employee's company.","example":true},"allowed":{"type":"integer","format":"int32","description":"Present only when enabled. Yearly allowance in days (the contract `ho_balance` override, else the company yearly cap).","example":20},"taken":{"type":"integer","format":"int32","description":"Present only when enabled. Approved home office already taken this year, in whole days.","example":5},"remaining":{"type":"integer","format":"int32","description":"Present only when enabled. Allowance still available, in whole days (`allowed` - `taken`). May be negative.","example":15}}},"overtime":{"type":"object","description":"Overtime calculation period summary. When `enabled` is false, only the\n`enabled` flag is present. When enabled, the additional fields below are\nincluded; `current_period` and `current` appear only when a period is\nactive for the current date.\n","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether overtime calculation periods are configured for the employee's company.","example":true},"decision_enabled":{"type":"boolean","description":"Present only when enabled. Whether overtime decisions are configured for the company.","example":true},"compensatory_balance":{"type":"string","description":"Present only when enabled. Employee compensatory balance for the company, `HH:MM:SS` (may be negative). This is the AVAILABLE balance: the snapshot from the last LOCKED period. The running period's undecided accrual is reported separately under `current_accrual`, never folded in here.\n","example":"12:30:00"},"compensatory_balance_seconds":{"type":"integer","format":"int32","description":"Same balance in seconds, so the client does not have to parse the string.","example":45000},"decision_preference":{"type":["object","null"],"description":"Present only when enabled. The employee's effective overtime decision\npreference: their own active preference, else the company's. Null when\nnone is configured, in which case the company auto-decision policy\napplies at period end. `level` reports which of the two the values\ncame from.\n","required":["level","preferred_decision","auto_decision_policy","max_seconds","rest_policy","policy_reason"],"properties":{"level":{"type":"string","enum":["employee","company"],"description":"Whether these values come from the employee's own preference or the inherited company default.","example":"employee"},"preferred_decision":{"type":["string","null"],"enum":["pay_up_to","increment_up_to",null],"description":"The default action for overtime (pay it out up to the cap, or add it to the balance up to the cap). Null when unset.","example":"increment_up_to"},"auto_decision_policy":{"type":["string","null"],"enum":["skip_if_manual_decision","force_auto_decision","force_zero_overtime",null],"description":"What the system does at period end when the employee makes no manual decision.","example":"skip_if_manual_decision"},"max_seconds":{"type":["integer","null"],"format":"int32","description":"Cap in seconds that the preferred decision applies up to (for example 36000 = 10 hours). Null when uncapped.","example":36000},"rest_policy":{"type":["string","null"],"enum":["add_to_balance","drop",null],"description":"What happens to overtime beyond the cap (carry it to the balance or drop it). Null when unset.","example":"add_to_balance"},"policy_reason":{"type":["string","null"],"description":"Free-text justification recorded with the preference. Null when none was given.","example":"Per HR overtime policy."}}},"current_period":{"type":"object","description":"The overtime calculation period containing the current date. Present only when enabled and an active period exists.","required":["id","start","end","decision_possible_from","decision_possible_to"],"properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the overtime period.","example":"550e8400-e29b-41d4-a716-446655440000"},"start":{"type":"string","format":"date","description":"First day of the overtime period.","example":"2026-01-01"},"end":{"type":"string","format":"date","description":"Last day of the overtime period.","example":"2026-12-31"},"decision_possible_from":{"type":["string","null"],"format":"date","description":"First day the employee may submit an overtime decision. Null when decisions are not enabled.","example":"2026-12-24"},"decision_possible_to":{"type":["string","null"],"format":"date","description":"Last day the employee may submit an overtime decision. Null when decisions are not enabled.","example":"2026-12-31"}}},"current_accrual":{"type":"object","description":"Overtime accrued within the current period through the last COMPLETED day, split by day type. Always present (zeros when no period is open). Every figure is a signed BALANCE in seconds, with a pre-formatted `HH:MM:SS` twin and a ready-made `total`, so a client can display it as-is or convert.\n\nThe range ends at YESTERDAY midnight \u2014 today is never counted. Today is still being lived, and the calculation charges the full workshift requirement against however much has been worked so far, so including it would show the rest of the day as undertime and make the figure climb hour by hour. Only finished days are stable enough to report as an accrued balance.\n\nEvery overtime surface uses this same cutoff \u2014 this endpoint, `GET \/{pbx_id}\/user\/{employee_id}\/user-overtime-decision\/getOvertime`, and the figure stored when a decision is submitted all report the identical number, so the accrual a client previews is the accrual the decision books.\n","required":["business","business_formatted","non_working","non_working_formatted","total","total_formatted"],"properties":{"business":{"type":"integer","format":"int32","description":"Balance accrued on business (working) days, in seconds. Negative when the period is running below the required time.","example":7200},"business_formatted":{"type":"string","description":"Same figure as `HH:MM:SS`, sign glued to the value (`-02:08:49`). Hours may exceed 24.","example":"02:00:00"},"non_working":{"type":"integer","format":"int32","description":"Balance accrued on non-working days, in seconds.","example":3600},"non_working_formatted":{"type":"string","description":"Same figure as `HH:MM:SS`, sign glued to the value.","example":"01:00:00"},"total":{"type":"integer","format":"int32","description":"`business` + `non_working`, in seconds. The figure to display as the period accrual.","example":10800},"total_formatted":{"type":"string","description":"Same total as `HH:MM:SS`, sign glued to the value.","example":"03:00:00"}}}}},"travel_time":{"type":"object","description":"Travel time allowance. When `enabled` is false, only the `enabled` flag is\npresent. When enabled, the employee may credit extra payable minutes to a\nday through POST \/{pbx_id}\/user\/{employee_id}\/travel-time, up to\n`max_per_day` times per date. The credited minutes are inserted immediately\nbefore the day's first status, so they extend the working day and count\ntoward work time and overtime.\n","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether travel time is enabled for this employee.","example":true},"minutes_per_request":{"type":"integer","format":"int32","description":"Present only when enabled. Payable minutes credited per request.","example":30},"max_per_day":{"type":"integer","format":"int32","description":"Present only when enabled. How many credits are allowed per date.","example":1},"used_today":{"type":"integer","format":"int32","description":"Present only when enabled. Credits already taken today.","example":0},"remaining_today":{"type":"integer","format":"int32","description":"Present only when enabled. Credits still available today.","example":1}}},"travel_time_allowed":{"type":"boolean","description":"Flat mirror of `travel_time.enabled`, for clients that read the flag directly. Always present and always consistent with the block.\n","example":true},"preferences":{"type":"object","description":"The employee user's Tempus display preferences. These describe how the\nuser prefers dates rendered; they do not change the format of any field\nin this response (dates here are always ISO `Y-m-d`). Always present, with\nthe user's stored choice or the system default.\n","required":["date_format"],"properties":{"date_format":{"type":"string","enum":["d\/m\/Y","m\/d\/Y","Y-m-d","d.m.Y"],"description":"The user's preferred date display format, as a PHP\/`date()` format\nstring. Falls back to the system default (`Y-m-d`) when the user has\nset no preference. A client can use this to render dates in the user's\npreferred style.\n","example":"d.m.Y"}}},"validator":{"type":["object","null"],"description":"The employee's validator role, or `null` when they hold none. Null is the\nsignal for whether to offer a validator section at all; a validator with an\nempty queue today is still a validator, so use `pending` for badges and\nempty states rather than to decide whether the section exists.\n\n`permissions` answers for both approval engines: the approval chains, and\nthe older validator rules while a tenant still has them.\n\nThe `companies`, `departments` and `employees` lists are the roster the older\nrules resolved, and are the values behind the filters for\n`GET \/{pbx_id}\/validator\/employees`. Approval chains cannot produce that\nroster cheaply: a validator's place is a position in each requester's own\nchain, resolved through that person's contract, so for a tenant configured\nonly with chains these three lists come back empty. Use `pending` and the\nqueue endpoints (`GET \/{pbx_id}\/validator\/pending-requests`,\n`pending-corrections`) instead, which answer from the chain itself.\n","required":["permissions","pending","companies","departments","employees"],"properties":{"permissions":{"type":"object","description":"Which validator modules this employee may act on.","properties":{"holiday_requests":{"type":"boolean"},"home_office_requests":{"type":"boolean"},"time_point_corrections_requests":{"type":"boolean"},"schedules_management":{"type":"boolean"}}},"pending":{"type":"object","description":"How many requests of each type are waiting on this employee right now,\ncounted from the approval rows addressed to them. Keyed the same way as\n`permissions`. `schedules_management` is always 0: schedule assignment is\ndirect management, not a request queue.\n","properties":{"holiday_requests":{"type":"integer","example":3},"home_office_requests":{"type":"integer","example":1},"time_point_corrections_requests":{"type":"integer","example":0},"schedules_management":{"type":"integer","example":0}}},"companies":{"type":"array","description":"Distinct companies in the validator's scope.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}},"departments":{"type":"array","description":"Distinct departments in the validator's scope.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}},"employees":{"type":"array","description":"Lightweight list of the employees the validator may consult.","items":{"type":"object","properties":{"employee_id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}}}},"validators":{"type":"array","description":"The other direction from `validator`: the people who validate THIS employee's\nrequests, one entry per validator, with the request types each of them covers.\nWhere `validator` says what this employee may approve, `validators` says who\napproves this employee.\n\nAlways present. Empty array when nobody validates the employee. Resolved from the\nolder validator rules on the same basis as the `validator` block, so on a tenant\nconfigured only with approval chains (which cannot answer \"who validates me\"\ncheaply) it comes back empty; drive off `pending` and the queue endpoints there.\n","items":{"type":"object","required":["employee_id","user_id","name","scopes"],"properties":{"employee_id":{"type":"string","format":"uuid","description":"The validator's Tempus employee id.","example":"550e8400-e29b-41d4-a716-446655440010"},"user_id":{"type":["string","null"],"format":"uuid","description":"The validator's linked Cockpit user id, or null when they have no linked user.","example":"550e8400-e29b-41d4-a716-446655440011"},"name":{"type":"string","description":"The validator's display name (the PBX name-order preference is applied).","example":"Jane Smith"},"scopes":{"type":"array","description":"The request types this validator covers for the employee, in a stable order.\nA validator who covers more than one type appears once with every type listed.\n","items":{"type":"string","enum":["holiday_requests","home_office_requests","time_point_corrections_requests","schedules_management"]},"example":["holiday_requests","time_point_corrections_requests"]}}}}}},"TempusTravelTimeCredit":{"type":"object","description":"One travel time credit: a payable block of minutes added to a day because the\nemployee requested it.\n\nEach credit is stored as an accepted time point correction (the \"create a new\ntime point\" shape) plus the time point it produced, so it appears in the\nemployee's correction history and can be corrected or removed like any other\ntime point.\n","properties":{"id":{"type":"string","format":"uuid","description":"UUID of the correction row that recorded the request.","example":"550e8400-e29b-41d4-a716-446655440010"},"date":{"type":"string","format":"date","description":"The date the credit was applied to.","example":"2026-05-11"},"start_time":{"type":"string","description":"Start of the credited block, `Y-m-d H:i:s`.","example":"2026-05-11 07:30:00"},"end_time":{"type":["string","null"],"description":"End of the credited block, `Y-m-d H:i:s`. Null only if the produced time point has since been left open by a later correction.\n","example":"2026-05-11 08:00:00"},"minutes":{"type":["integer","null"],"format":"int32","description":"Length of the credited block in whole minutes. Normally the configured allowance, but smaller when the block had to be clamped to the start of the day. Null when `end_time` is null.\n","example":30},"status_id":{"type":"string","format":"uuid","description":"UUID of the PBX travel time status the credit was recorded on.","example":"550e8400-e29b-41d4-a716-446655440011"},"timepoint_id":{"type":["string","null"],"format":"uuid","description":"UUID of the time point the credit produced.","example":"550e8400-e29b-41d4-a716-446655440012"},"comment":{"type":["string","null"],"description":"The comment stored with the credit.","example":"Travel time requested"},"created_at":{"type":["string","null"],"description":"When the credit was recorded, `Y-m-d H:i:s`.","example":"2026-05-11 12:00:00"}}},"TempusUserCompany":{"type":"object","description":"Association between a Tempus employee and a company, as serialized by the V1\n`UserCompanyResource`. Each record is backed by a Tempus contract row and\ndescribes the employee's participation in one company: their working-time\nbalances, contract period, job title, and the company's payroll-relevant\nsettings.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Field names are remapped for the integration audience\n(for example the contract `pbx_id` is exposed as `mxvp_user_id`, and the\ncontract `job_title` is exposed as `title`). The nested `company` object is\nalways present and carries a subset of the related company's fields; its\nscalar values are null when no company is linked.\n\nMonetary and balance values are normalized in the resource: `participation`\nand `ho_balance` are cast to floating-point numbers, `compensatory_balance`\nis cast to an integer (defaulting to 0 rather than null), and `main_company`\nis emitted as the integer 1 or 0 rather than a boolean.\n","required":["id","mxvp_user_id","ext_id","company_id","participation","contract_start","contract_end","main_company","compensatory_balance","ho_balance","title","department_id","delete_date","company"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the employee-company association (the underlying Tempus contract id).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this association. Maps to the contract's `pbx_id`.","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_id":{"type":["string","null"],"description":"External extension identifier resolved for the linked employee, or null\nwhen the employee has no associated extension.\n","example":"1001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the company this association links to. Null when no company is set.","example":"550e8400-e29b-41d4-a716-446655440002"},"participation":{"type":["number","null"],"format":"float","description":"Employee's participation ratio in the company, expressed as a fractional\nvalue (for example 1.0 for full participation, 0.5 for half). Null when\nnot configured.\n","example":1},"contract_start":{"type":["string","null"],"format":"date-time","description":"Start of the contract period, in ISO 8601 format. Null when not set.","example":"2024-01-01T00:00:00.000000Z"},"contract_end":{"type":["string","null"],"format":"date-time","description":"End of the contract period, in ISO 8601 format. Null for an open-ended contract.","example":"2025-12-31T00:00:00.000000Z"},"main_company":{"type":"integer","format":"int32","enum":[0,1],"description":"Whether this is the employee's main (primary) company. Emitted as the\ninteger 1 when true and 0 when false.\n","example":1},"compensatory_balance":{"type":"integer","format":"int32","description":"Accrued compensatory time balance for the employee, in seconds. Defaults\nto 0 when no balance is recorded (never null).\n","example":3600},"ho_balance":{"type":["number","null"],"format":"float","description":"Home-office (remote work) balance for the employee, expressed in the\nconfigured balance unit. Null when not tracked.\n","example":8.5},"title":{"type":["string","null"],"description":"Job title held by the employee under this contract. Maps to the contract's `job_title`. Null when unset.","example":"Sales Representative"},"department_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the department the employee belongs to within the company. Null when unassigned.","example":"550e8400-e29b-41d4-a716-446655440003"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-deletion timestamp of the association, in ISO 8601 format. Null when\nthe association is active (not deleted).\n","example":null},"company":{"type":"object","description":"Subset of the linked company's details. Always present as an object; its\nscalar fields are null when no company is associated with this contract.\n","required":["id","mxvp_user_id","company","address","country_cc","legalHolidays","full_time","salary_lu_id","overtime_calculation_period_enabled","overtime_decision_enabled","delete_date"],"properties":{"id":{"type":["string","null"],"format":"uuid","description":"Unique identifier of the company. Null when no company is linked.","example":"550e8400-e29b-41d4-a716-446655440002"},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns the company. Maps to the company's `pbx_id`.","example":"550e8400-e29b-41d4-a716-446655440001"},"company":{"type":["string","null"],"description":"Display name of the company. Maps to the company's `name`. Null when no company is linked.","example":"Sales Team"},"address":{"type":["string","null"],"description":"Single-line postal address composed of the company's street, postal\ncode, and city (joined by spaces). Null when none of those parts are\nset.\n","example":"100 Market Street 10001 New York"},"country_cc":{"type":["string","null"],"description":"ISO country code of the company's country. Null when no country is set.","example":"US"},"legalHolidays":{"type":["number","null"],"format":"float","description":"Number of legally mandated paid leave days granted per year. Maps to\nthe company's `legal_paid_leaves_yearly_days`. Null when not\nconfigured.\n","example":26},"full_time":{"type":["integer","null"],"format":"int32","description":"Full-time working time reference for the company, expressed in\nseconds. Maps to the company's `full_time_seconds`. Null when no\ncompany is linked.\n","example":144000},"salary_lu_id":{"type":"null","description":"Reserved field for a salary lookup identifier. Currently always null\n(not yet populated by the API).\n","example":null},"overtime_calculation_period_enabled":{"type":"boolean","description":"Whether overtime is calculated over a defined accounting period for this company. Defaults to false.","example":false},"overtime_decision_enabled":{"type":"boolean","description":"Whether overtime requires explicit approval (decision) for this company. Defaults to false.","example":false},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-deletion timestamp of the company, in ISO 8601 format. Null when the company is active.","example":null}}}}},"TempusHomeOfficeCalendar":{"type":"object","description":"Virtual home office calendar entry for a single employee and calendar year, as\nserialized by the V1 `HomeOfficeCalendarResource`. This object is not backed by\na dedicated table: it is derived on the fly from `TempusTransaction` records of\ntype `home_office`, then grouped by employee, company, and year. The response\nshape is preserved for backward compatibility with the legacy\n`TempusHomeOfficeCalendar` resource, so several values are denormalized into\nthis single object rather than exposed as relations.\n\nEach day a home office request touches is classified into one of three date\nlists based on the source transaction's status and sub-type: pending requests\ngo into `requested_days`, approved requests into `approved_days`, and pending\nremovals or rejected requests into `removed_days`. Every date is an ISO 8601\ncalendar date (YYYY-MM-DD) and the lists are deduplicated. The matching\n`count_*` fields hold the number of entries in each list.\n\nThe `user` object is only present when the calendar is requested with employee\nuser details included (the `includeUser` option); it is absent otherwise.\n","required":["id","mxvp_user_id","ext_id","company_id","creator_id","validator_id","year","days_of_week","requested_days","approved_days","removed_days","comment","created","modified","count_requested_days","count_approved_days","count_removed_days"],"properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the underlying `TempusTransaction` (home office request) that\nseeded this calendar entry. Not a stable identifier of the calendar itself,\nwhich is a virtual aggregate.\n","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this calendar. Named `mxvp_user_id`\nfor backward compatibility with the legacy API; it corresponds to the\ntransaction's `pbx_id`.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_id":{"type":["string","null"],"description":"External identifier of the employee's primary extension, resolved from the\nemployee record. Null when the employee has no associated extension.\n","example":"201"},"company_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the company the home office requests belong to. Null when the\nrequests are not scoped to a specific company.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"creator_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee who created the home office request\n(the transaction requester, falling back to the subject employee). This is\na `tempus_employees` identifier, not a user identifier.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"validator_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus employee who validated (approved) the request,\nresolved from the approving user. Null when the request has not yet been\nvalidated. This is a `tempus_employees` identifier, not a user identifier.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"year":{"type":"integer","format":"int32","description":"Calendar year this entry aggregates. All dates in the day lists fall within\nthis year.\n","example":2026},"days_of_week":{"type":"string","description":"Comma-separated list of weekday abbreviations on which home office is\nconsidered applicable. Currently a fixed working-week value.\n","example":"mon,tue,wed,thu,fri"},"requested_days":{"type":"array","description":"Calendar dates with a pending home office request (not yet approved). Each\nentry is an ISO 8601 date (YYYY-MM-DD). Deduplicated; may be empty.\n","items":{"type":"string","format":"date","example":"2026-06-15"}},"approved_days":{"type":"array","description":"Calendar dates on which home office has been approved. Each entry is an\nISO 8601 date (YYYY-MM-DD). Deduplicated; may be empty.\n","items":{"type":"string","format":"date","example":"2026-06-16"}},"removed_days":{"type":"array","description":"Calendar dates that were removed: pending removals or rejected requests.\nEach entry is an ISO 8601 date (YYYY-MM-DD). Deduplicated; may be empty.\n","items":{"type":"string","format":"date","example":"2026-06-17"}},"comment":{"type":"string","description":"Free-form note carried over from the most recent contributing home office\ntransaction. Empty string when no note was provided.\n","example":"Working from home on project deadline week"},"created":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp when the seeding transaction was created. Null when the\ntimestamp is unavailable.\n","example":"2026-06-01T08:29:07+00:00","readOnly":true},"modified":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp when the seeding transaction was last updated. Null when\nthe timestamp is unavailable.\n","example":"2026-06-10T14:12:33+00:00","readOnly":true},"count_requested_days":{"type":"integer","format":"int32","description":"Number of distinct dates in `requested_days`.","example":1},"count_approved_days":{"type":"integer","format":"int32","description":"Number of distinct dates in `approved_days`.","example":1},"count_removed_days":{"type":"integer","format":"int32","description":"Number of distinct dates in `removed_days`.","example":1},"user":{"type":"object","description":"Summary of the employee's linked Voxbi user. Only present when the calendar\nis requested with user details included; omitted otherwise.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the linked user.","example":"550e8400-e29b-41d4-a716-446655440005"},"number":{"type":["string","null"],"description":"Extension number assigned to the user. Null when none is set.","example":"201"},"name":{"type":["string","null"],"description":"First name of the user.","example":"Jane"},"name2":{"type":["string","null"],"description":"Last name of the user.","example":"Smith"}}}}},"TempusPublicHoliday":{"type":"object","description":"Tempus public holiday as serialized by the V1 `TempusPublicHolidayResource`.\nA public holiday marks a non-working (or partially non-working) day used by the\nTempus time and attendance module when computing worked hours, leave, and pay.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Two fields are renamed or derived on output: the tenant\nidentifier is exposed as `mxvp_user_id` (falling back to the authenticated\ncaller's PBX when the holiday has no own `pbx_id`), and the model `duration`\ncolumn is exposed as `halfday`. The `country_cc` value is the ISO 3166-1\nalpha-2 code resolved from the related `Country` record. Date and timestamp\nvalues are emitted as ISO 8601 strings.\n","required":["id","name","date","halfday"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique public holiday identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns this public holiday. Sourced from\nthe holiday's own `pbx_id` and, when that is absent, from the authenticated\ncaller's PBX. Null only when neither the holiday nor the caller resolves to\na PBX.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Human-readable name of the public holiday.","example":"New Year's Day"},"date":{"type":"string","format":"date-time","description":"Calendar date of the public holiday, emitted as an ISO 8601 timestamp at\nthe start of that day in the application timezone.\n","example":"2024-01-01T00:00:00+00:00"},"halfday":{"type":"string","enum":["fullday","halfam","halfpm"],"description":"Portion of the day the holiday applies to: `fullday` for an entire\nnon-working day, `halfam` for a non-working morning, and `halfpm` for a\nnon-working afternoon.\n","example":"fullday"},"country_cc":{"type":["string","null"],"minLength":2,"maxLength":2,"description":"ISO 3166-1 alpha-2 country code of the holiday's associated country (for\nexample `LU` or `US`), resolved from the related `Country` record. Null\nwhen the holiday is not linked to a country.\n","example":"US"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp, emitted as an ISO 8601 string. Null for active\nholidays; populated only when the holiday has been soft-deleted and is\nreturned in a trashed listing.\n","example":null,"readOnly":true}}},"TempusOvertimeCalculationPeriod":{"type":"object","description":"A Tempus overtime calculation period as serialized by the V1\n`OvertimeCalculationPeriodResource`. An overtime period defines a bounded\nwindow (`start` to `end`) over which an employee's overtime balance is\naccumulated and, once finalized, locked against further changes.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The `ext_id` field is resolved dynamically: it prefers the\ntelephony extension identifier of the linked employee and falls back to the\nunderlying user identifier when no extension is linked. The `locked` flag is\nderived from the period's status (true only when the status is `locked`), and\n`delete_date` reflects the soft-delete timestamp (the period is normally only\npresent in responses while not deleted).\n\nTimestamp fields (`start`, `end`, `delete_date`) are serialized as ISO 8601\nstrings in UTC.\n","required":["id","mxvp_user_id","company_id","ext_id","start","end","locked","delete_date"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the overtime calculation period.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this period. Mirrors the model's\n`pbx_id` column, exposed under the integration-facing `mxvp_user_id` name.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus company this period belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"ext_id":{"type":["string","null"],"format":"uuid","description":"External reference for the employee the period applies to. Resolved to the\ntelephony extension identifier of the linked employee when one exists,\notherwise falling back to the underlying user identifier. Null when the\nperiod is not associated with any user.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"start":{"type":["string","null"],"format":"date-time","description":"Start of the overtime calculation window, serialized as an ISO 8601\nUTC timestamp. Null when no start date is set.\n","example":"2024-03-01T00:00:00.000000Z"},"end":{"type":["string","null"],"format":"date-time","description":"End of the overtime calculation window, serialized as an ISO 8601\nUTC timestamp. Null when no end date is set.\n","example":"2024-03-31T00:00:00.000000Z"},"locked":{"type":"boolean","description":"Whether the period is locked. True only when the period's status is\n`locked`, meaning its overtime balance is finalized and no longer editable.\nFalse for all other statuses (draft, open, ongoing, processed).\n","example":false},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp, serialized as an ISO 8601 UTC timestamp. Null for\nactive (non-deleted) periods, which is the usual case in API responses.\n","example":null}}},"TempusUserOvertimeDecision":{"type":"object","description":"A single overtime decision recorded against an employee for a given overtime\ncalculation period. A decision captures how an employee's accrued overtime\nbalance is resolved: how much is paid out, converted, reset, or carried\nforward, together with the resulting new balance.\n\nAll duration fields (`decision_balance`, `decision_overtime`, `to_pay`,\n`to_increment`, `to_convert`, `to_reset`, `decision_new_balance`) are\nexpressed as a whole number of seconds. They are returned as raw integer\nsecond counts, not as the HHH:MM display strings used in the admin UI.\n\nThe related calculation period is only present in the response under\n`overtime_calculation_period` when it has been explicitly loaded by the\nendpoint (eager loaded); otherwise the field is omitted.\n\n**Rows for a period that is still running are computed live.** An employee\ndecides once, part-way through the period, and then keeps working, so the\nfigures stored on the row are a snapshot of that moment and go out of date\nimmediately. On `GET \/{pbx_id}\/user\/{employee_id}\/user-overtime-decision`,\nsuch a row therefore reports `decision_balance`, `decision_overtime`,\n`to_increment` and `decision_new_balance` as they stand right now, against the\ndecision the employee made, and `values_live` is true. Settled history \u2014 a\nprocessed row, or any row whose period has ended \u2014 is returned exactly as\nstored. See `values_live` below.\n","required":["id","mxvp_user_id","ext_id","overtime_calculation_period_id","decision_type","decision","decision_balance","decision_overtime","to_pay","to_pay_extra","to_increment","to_convert","to_reset","decision_new_balance","comment","locked","values_live","created"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the overtime decision.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this decision.","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_id":{"type":["string","null"],"description":"External extension identifier of the employee the decision applies to,\nresolved from the employee record. Null when the employee has no\nassociated extension.\n","example":"1042"},"overtime_calculation_period_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the overtime calculation period this decision belongs to.\nNull when the decision is not linked to a specific period.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"decision_type":{"type":"string","enum":["manual","automatic"],"description":"How the decision was created. Defaults to `manual` when not otherwise\nset. `manual` decisions are entered by an operator, `automatic` decisions\nare produced by the system.\n","example":"manual"},"decision":{"type":["string","null"],"description":"The chosen resolution applied to the employee's overtime balance for the\nperiod (for example whether the overtime is paid out, converted, or\nreset). Null when no resolution has been selected yet.\n","example":"pay_out"},"decision_balance":{"type":"integer","format":"int32","description":"The employee's overtime balance, in seconds, carried into this period:\nthe `decision_new_balance` of the last LOCKED period, or the contract's\nopening base when nothing has been locked yet. Maps to the model's\n`old_balance`.\n","example":36000},"decision_overtime":{"type":"integer","format":"int32","description":"The overtime accrued during the period, in seconds, that this decision\nresolves. Counted over COMPLETED days only \u2014 the range ends at yesterday\nmidnight, so neither the remaining workdays nor the hours still owed on\ntoday are counted as undertime. (A day carries its full shift requirement\nfrom the moment it begins, so a day in progress always reads negative.)\nNegative when the employee genuinely worked less than required over those\ncompleted days. Maps to the model's `overtime`.\n\nOn a running period this is recomputed per request and keeps moving until\nthe period closes; see `values_live`.\n","example":7200},"to_pay":{"type":"integer","format":"int32","description":"Amount of overtime, in seconds, to be paid out to the employee. Never\nnegative and never more than `decision_balance + decision_overtime`.\n\nThis is the employee's own commitment to cash out a given amount, so it is\nNOT re-derived on a live row even as the accrual grows \u2014 it is only clamped\ndown if it would exceed what is available. The growth lands on\n`to_increment` instead.\n","example":3600},"to_pay_extra":{"type":"integer","format":"int32","description":"Additional overtime to pay out, in seconds. Always returned as 0 by this\nendpoint (reserved for future use).\n","example":0},"to_increment":{"type":"integer","format":"int32","description":"Amount of overtime, in seconds, added to the employee's balance:\n`decision_overtime - to_pay`. Negative when the payout is larger than the\nperiod's accrual (the difference is drawn from the carried-in balance), or\nwhen the period itself ended in undertime.\n","example":0},"to_convert":{"type":"integer","format":"int32","description":"Amount of overtime, in seconds, to be converted (for example into leave\nor another balance type).\n","example":1800},"to_reset":{"type":"integer","format":"int32","description":"Amount of overtime, in seconds, to be reset (discarded) from the balance.","example":0},"decision_new_balance":{"type":"integer","format":"int32","description":"The resulting overtime balance, in seconds, after applying this decision \u2014\nwhat the employee has left once the payout is taken out. Derived by the\nsystem as\n`decision_balance + decision_overtime - to_pay - to_convert - to_reset`.\nMaps to the model's `new_balance`.\n","example":38400},"comment":{"type":["string","null"],"description":"Optional free-form note explaining or justifying the decision.","example":"Carried forward at the employee's request"},"locked":{"type":"boolean","description":"Whether the decision has been processed and locked. True once the\ndecision has a processing timestamp, after which it should be treated as\nfinal and immutable.\n","example":false},"values_live":{"type":"boolean","description":"Whether the duration fields on this row were computed just now rather than\nread from the decision snapshot.\n\nTrue only for a row whose period is still running and which has not been\nprocessed. Those figures are a moving target \u2014 they change as the employee\nkeeps working, and are final only once the period closes and the decision\nis locked. False for all settled history, where the stored values are\nreturned verbatim.\n","example":false},"created":{"type":["string","null"],"description":"Timestamp when the decision was created, formatted as `Y-m-d H:i:s`\n(for example `2024-03-01 08:29:07`). Null when the creation timestamp is\nnot set.\n","example":"2024-03-01 08:29:07","readOnly":true},"overtime_calculation_period":{"type":"object","description":"The related overtime calculation period this decision belongs to. Only\npresent when the relation has been eager loaded by the endpoint;\notherwise the field is omitted from the response.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the overtime calculation period.","example":"550e8400-e29b-41d4-a716-446655440002","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns the period.","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus company the period belongs to.","example":"550e8400-e29b-41d4-a716-446655440003"},"ext_id":{"type":["string","null"],"description":"External extension identifier of the employee, falling back to the\nperiod's user identifier when the employee has no extension.\n","example":"1042"},"start":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp marking the start of the calculation period.","example":"2024-03-01T00:00:00Z"},"end":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp marking the end of the calculation period.","example":"2024-03-31T23:59:59Z"},"locked":{"type":"boolean","description":"Whether the calculation period is locked and no longer editable.","example":false},"delete_date":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp when the period was soft deleted. Null while the\nperiod is active.\n","example":null}}}}},"TempusOvertimeDecisionPreference":{"type":"object","description":"The employee level overtime decision preference: the standing rule that tells\nthe nightly overtime job what to do with the overtime this employee produces.\n\nIt is the same row HR edits on the employee record under \"Decision\nPreferences\", stored in `tempus_overtime_decision_preferences`. An employee\nhas at most one of these. When it is absent the company level preference\napplies instead.\n\nWhen `auto_decision_policy` is `force_zero_overtime` the employee is not\neligible for overtime at all, so `preferred_decision`, `max_seconds` and\n`rest_policy` are always null.\n","properties":{"id":{"type":"string","format":"uuid","description":"UUID of the preference row.","example":"9b1f0c62-4d0a-4e2f-9f43-6f4a5c8d1e70"},"scope":{"type":"string","enum":["employee"],"description":"Always `employee` on this endpoint. Company level rows are managed by HR only.","example":"employee"},"employee_id":{"type":"string","format":"uuid","description":"UUID of the employee the preference belongs to.","example":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed"},"auto_decision_policy":{"type":"string","enum":["skip_if_manual_decision","force_auto_decision","force_zero_overtime"],"description":"How the automatic overtime decision behaves.\n\n| value | meaning |\n|---|---|\n| `skip_if_manual_decision` | Leave the period alone when a manual decision already exists. |\n| `force_auto_decision` | Always apply the automatic decision, overriding a manual one. |\n| `force_zero_overtime` | The employee is not eligible for overtime. |\n","example":"force_auto_decision"},"auto_decision_policy_label":{"type":"string","description":"Human readable label for `auto_decision_policy`, translated to the request locale.","example":"Force auto-decision (override manual)"},"policy_reason":{"type":["string","null"],"maxLength":1000,"description":"Free text note explaining why this policy was chosen.","example":"Prefers time off over payout"},"preferred_decision":{"type":["string","null"],"enum":["pay_up_to","increment_up_to",null],"description":"What to do with the overtime, up to the `max_seconds` cap. Null when\n`auto_decision_policy` is `force_zero_overtime`.\n\n| value | meaning |\n|---|---|\n| `pay_up_to` | Pay the overtime out, up to the cap. |\n| `increment_up_to` | Add the overtime to the compensatory balance, up to the cap. |\n","example":"pay_up_to"},"preferred_decision_label":{"type":["string","null"],"description":"Human readable label for `preferred_decision`.","example":"Pay up to X hours"},"max_seconds":{"type":["integer","null"],"format":"int32","minimum":3600,"maximum":115200,"description":"The cap in seconds, from 3600 (1 hour) to 115200 (32 hours). Null when `auto_decision_policy` is `force_zero_overtime`.\n","example":28800},"max_hours":{"type":["number","null"],"format":"float","description":"The same cap expressed in hours, rounded to two decimals. Convenience mirror of `max_seconds`.","example":8},"rest_policy":{"type":["string","null"],"enum":["add_to_balance","drop",null],"description":"What happens to the overtime left over above the cap. Null when\n`auto_decision_policy` is `force_zero_overtime`.\n\n| value | meaning |\n|---|---|\n| `add_to_balance` | Carry the remainder into the compensatory balance. |\n| `drop` | Discard the remainder. |\n","example":"add_to_balance"},"rest_policy_label":{"type":["string","null"],"description":"Human readable label for `rest_policy`.","example":"Add to balance"},"is_active":{"type":"boolean","description":"Whether the preference is applied. A deactivated row is kept but ignored.","example":true},"created_at":{"type":["string","null"],"description":"When the preference was first saved, `Y-m-d H:i:s`.","example":"2026-08-06 09:14:22"},"updated_at":{"type":["string","null"],"description":"When the preference was last changed, `Y-m-d H:i:s`.","example":"2026-08-06 10:02:51"}}},"TempusOvertimeDecisionPreferenceMeta":{"type":"object","description":"Everything a client needs to render the preference form without hardcoding the enums: the selectable values with their translated labels, the bounds of the cap, and the values that apply when the employee has never saved a preference.\n","required":["configured","options","limits","defaults"],"properties":{"configured":{"type":"boolean","description":"Whether an employee level preference row exists. False means `data` is null and the company level rule applies.","example":true},"options":{"type":"object","description":"Selectable values keyed by field name. Each entry maps the stored value to its translated label.","required":["auto_decision_policy","preferred_decision","rest_policy"],"properties":{"auto_decision_policy":{"type":"object","additionalProperties":{"type":"string"},"example":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"}},"preferred_decision":{"type":"object","additionalProperties":{"type":"string"},"example":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"}},"rest_policy":{"type":"object","additionalProperties":{"type":"string"},"example":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}}}},"limits":{"type":"object","description":"Accepted range for the cap, in both units.","required":["min_seconds","max_seconds","min_hours","max_hours"],"properties":{"min_seconds":{"type":"integer","format":"int32","example":3600},"max_seconds":{"type":"integer","format":"int32","example":115200},"min_hours":{"type":"number","format":"float","example":1},"max_hours":{"type":"number","format":"float","example":32}}},"defaults":{"type":"object","description":"The values the form should start from when `configured` is false.","properties":{"auto_decision_policy":{"type":"string","example":"skip_if_manual_decision"},"preferred_decision":{"type":"string","example":"pay_up_to"},"rest_policy":{"type":"string","example":"add_to_balance"},"max_seconds":{"type":"integer","format":"int32","example":3600},"max_hours":{"type":"number","format":"float","example":1},"is_active":{"type":"boolean","example":true}}}}},"TempusCompiledUserWorkshift":{"type":"object","description":"A single compiled (precomputed) workshift entry for one Tempus employee on one\ncalendar day, as serialized by the V1 `CompiledUserWorkshiftResource`. Each\nrecord summarizes the worked time the Tempus engine has rolled up for that day,\nattributing it to the employee's effective work shift and the ISO-style work\nweek it falls into.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase column names. Several keys are intentionally renamed for the public\nAPI: `mxvp_user_id` is the owning Pbx (tenant) identifier, `ext_id` is the\nTempus employee identifier, and `user_workshift_id` is the linked employee\nwork-shift identifier. The `date` value is normalized to a calendar date\n(YYYY-MM-DD), while `create_time` is the record's creation timestamp formatted\nas `YYYY-MM-DD HH:MM:SS`.\n\nRecords are read-only: they are produced by the Tempus compilation process and\nexposed through the list endpoint, which supports `from`\/`to` date filtering\nand sorting by `date`.\n","required":["id","mxvp_user_id","ext_id","user_workshift_id","date","workshift_week","worktime","create_time"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the compiled workshift record.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this record (the raw `pbx_id`\ncolumn). Named `mxvp_user_id` in the public API for historical reasons.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"ext_id":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee this compiled workshift belongs to (the\nraw `employee_id` column).\n","example":"550e8400-e29b-41d4-a716-446655440002"},"user_workshift_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee work shift this entry was compiled against (the\nraw `employee_work_shift_id` column). Null when no specific work shift was\nassociated with the day.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"date":{"type":["string","null"],"format":"date","description":"Calendar day this entry summarizes, normalized to YYYY-MM-DD. Null only if\nno date is set on the underlying record.\n","example":"2024-03-01"},"workshift_week":{"type":"integer","format":"int32","description":"Week number the day falls into within the work-shift cycle, used to group\ndaily entries into weekly totals.\n","example":9},"worktime":{"type":"integer","format":"int32","description":"Total compiled worked time for the day, expressed in seconds.\n","example":28800},"create_time":{"type":["string","null"],"description":"Timestamp when the record was created, formatted as `YYYY-MM-DD HH:MM:SS`\n(not ISO 8601). Null when the underlying creation timestamp is not set.\n","example":"2024-03-01 08:29:07","readOnly":true}}},"TempusScheduleSummary":{"type":"object","description":"Tempus schedule (planning grid) as serialized by the V1 `ScheduleResource`. A\nschedule defines the time-attendance planning view for a single Tempus\ndepartment: which weekdays are shown, the visible time window each day, and the\ngranularity of the time slots in the grid. It optionally pins a default status\nand sub-status applied to new entries.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. Several values are reshaped by the resource:\n`days_to_display` is a 7-character bitmask string derived from the stored\n`days_of_week` array, and `slot_duration` is an `HH:MM:SS` time string derived\nfrom the stored `slot_duration_minutes` integer.\n\nA schedule also defines WHO it is for, via `scope_type`: whole companies, one or\nmore groups (departments), or a hand-picked list of employees. `groups` lists every\ngroup the schedule covers and `employees` everyone who may be booked into its slots;\nbuild an assignment picker from `employees`.\n\nThe `group` object mirrors the schedule's anchor group and is only present when the\n`department` relation is loaded on the model; it is omitted otherwise. Both `group`\nand `group_id` are null when the scope resolves to no group at all, which happens\nfor a company-scoped schedule whose people hold contracts carrying no department.\nThe `mxvp_user_id` at the top level is the schedule's own tenant (Pbx) identifier and\nis always present.\n","required":["id","mxvp_user_id","name","group_id","scope_type","groups","employees","days_to_display","slot_min_time","slot_max_time","slot_duration","status_id","sub_status_id","delete_date"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique schedule identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"mxvp_user_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this schedule. Read from the schedule\nitself, so it is always present, including for a schedule with no anchor group.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Human-readable name of the schedule.","example":"Customer Support"},"group_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus department (planning group) this schedule is anchored\nto. Mirrors the model's `department_id`.\n\nNull when the schedule's scope resolves to no group, which happens for a\ncompany-scoped schedule whose people hold contracts carrying no department. Such\na schedule is valid and fully usable: its people come from the company. Treat\nthis field as optional and use `groups` for the full list.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"days_to_display":{"type":"string","description":"Seven-character bitmask string indicating which weekdays are shown in the\nplanning grid, ordered Monday through Sunday. Each position is \"1\" when the\nday is visible and \"0\" when it is hidden (for example \"1111100\" shows\nMonday to Friday). Derived from the stored `days_of_week` array.\n","example":"1111100"},"slot_min_time":{"type":["string","null"],"description":"Start of the visible time window for each day, as an `HH:MM` time string.\nNull when no start time is configured.\n","example":"08:00"},"slot_max_time":{"type":["string","null"],"description":"End of the visible time window for each day, as an `HH:MM` time string.\nNull when no end time is configured.\n","example":"18:00"},"slot_duration":{"type":"string","description":"Duration of a single time slot in the planning grid, as an `HH:MM:SS` time\nstring. Derived from the stored `slot_duration_minutes` integer (for\nexample 30 minutes becomes \"00:30:00\"); defaults to 30 minutes.\n","example":"00:30:00"},"status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default Tempus status applied to entries created in this\nschedule. Null when no default status is set.\n","example":"550e8400-e29b-41d4-a716-446655440003"},"sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default Tempus sub-status applied to entries created in\nthis schedule. Null when no default sub-status is set.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp for the schedule, as a `YYYY-MM-DD HH:MM:SS` string.\nNull when the schedule is active (not soft-deleted).\n","example":"2024-03-01 08:29:07","readOnly":true},"group":{"type":["object","null"],"description":"The schedule's anchor Tempus department, included only when the `department`\nrelation is loaded on the model; the key is omitted entirely otherwise. Null when\nthe scope resolves to no group (see `group_id`).\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the department.","example":"550e8400-e29b-41d4-a716-446655440002"},"mxvp_user_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Pbx (tenant) that owns the department. Null when no\ntenant is associated.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the department.","example":"Sales Team"},"delete_date":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp for the department, as a\n`YYYY-MM-DD HH:MM:SS` string. Null when the department is active.\n","example":"2024-03-01 08:29:07","readOnly":true}}},"scope_type":{"type":"string","enum":["company","department","employees"],"description":"Who the schedule is for:\n\n- `company`: everyone contracted with the selected companies.\n- `department`: everyone contracted in the selected groups (the default, and what\n  a schedule created without a `scope_type` gets).\n- `employees`: exactly the selected people, who may come from different groups and\n  different companies.\n","example":"department"},"groups":{"type":"array","description":"Every group (department) the schedule covers, resolved from its scope. One entry for a classic single-group schedule; empty when the scope resolves to no group. `filter[group_id]` on the list endpoint matches against this, not only against the anchor `group_id`.\n","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the group.","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":["string","null"],"description":"Display name of the group.","example":"Sales Team"}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440002","name":"Sales Team"}]},"employees":{"type":"array","description":"Everyone who may be booked into the schedule's slots, resolved from its scope. Build an assignment picker from this list; booking anybody outside it is refused with a 422. The group fields are those of the employee's most recent contract and are null when that contract carries no department.\n","items":{"type":"object","required":["id","full_name","group_id","group_name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the employee.","example":"550e8400-e29b-41d4-a716-446655440010"},"full_name":{"type":"string","description":"Display name of the employee.","example":"Jane Smith"},"group_id":{"type":["string","null"],"format":"uuid","description":"Group on the employee's most recent contract, or null.","example":"550e8400-e29b-41d4-a716-446655440002"},"group_name":{"type":["string","null"],"description":"Name of that group, or null.","example":"Sales Team"}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440010","full_name":"Jane Smith","group_id":"550e8400-e29b-41d4-a716-446655440002","group_name":"Sales Team"}]}}},"TempusScheduleManagement":{"type":"object","description":"Tempus schedule template as serialized by the `ScheduleResource`. A schedule\ndefines a recurring planning grid: which weekdays it covers, the daily working\nwindow (start and end time), and the granularity of each bookable slot. It\noptionally pins a default status and sub-status applied to generated entries, and\ncan restrict the statuses selectable on the grid.\n\nA schedule also defines WHO it is for, via `scopeType`: whole companies, one or\nmore departments, or a hand-picked list of employees. `scope` reports the raw\nselection (only the list matching `scopeType` is populated), while `departments`\nand `employees` report the resolved coverage. `employees` is the definitive list of\npeople who may be booked into the schedule's slots, and is what an assignment\npicker should be built from.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The `department`, `status`, and `subStatus` fields are\nrelationship objects that are only present when the corresponding relation is\neager-loaded on the model; when not loaded they are omitted from the payload\nentirely. The `dayStartTime` and `dayEndTime` values are returned trimmed to\n`HH:MM` (seconds are dropped). Times are local wall-clock values with no\ntimezone component.\n","required":["id","name","scopeType","scope","departments","employees","daysOfWeek","dayStartTime","dayEndTime","slotDurationMinutes","statusFilters","isActive","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique schedule identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"name":{"type":"string","description":"Human-readable name of the schedule template.","example":"Sales Team Weekly Plan"},"department":{"type":["object","null"],"description":"The schedule's anchor department. Only present when the `department` relation is\neager-loaded; otherwise this key is omitted.\n\nNull when the scope resolves to no department at all, which happens for a\ncompany-scoped schedule whose people hold contracts carrying no department. Such\na schedule is valid and fully usable: its people come from the company. Treat\nthis field as optional. Use `departments` for the full list of departments the\nschedule covers.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the department.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the department.","example":"Customer Support"}}},"scopeType":{"type":"string","enum":["company","department","employees"],"description":"Who the schedule is for:\n\n- `company`: everyone contracted with the selected companies.\n- `department`: everyone contracted in the selected departments (the default,\n  and what a schedule created without a `scope_type` gets).\n- `employees`: exactly the selected people, who may come from different\n  departments and different companies.\n","example":"department"},"scope":{"type":"object","description":"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.\n","required":["companies","departments","employees"],"properties":{"companies":{"type":"array","description":"Selected companies. Populated only when `scopeType` is `company`.","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the company.","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","description":"Display name of the company.","example":"Northwind Trading"}}},"example":[]},"departments":{"type":"array","description":"Selected departments. Populated only when `scopeType` is `department`.","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the department.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the department.","example":"Customer Support"}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440001","name":"Customer Support"}]},"employees":{"type":"array","description":"Selected employees. Populated only when `scopeType` is `employees`.","items":{"type":"object","required":["id","fullName"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the employee.","example":"550e8400-e29b-41d4-a716-446655440010"},"fullName":{"type":"string","description":"Display name of the employee.","example":"Jane Smith"}}},"example":[]}}},"departments":{"type":"array","description":"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.\n","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the department.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"description":"Display name of the department.","example":"Customer Support"}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440001","name":"Customer Support"}]},"employees":{"type":"array","description":"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`.\n","items":{"type":"object","description":"One assignable person of a schedule: an employee the schedule's scope covers and\nwho may therefore be booked into its slots.\n\nOnly employees holding a contract that is active today are listed \u2014 someone who has\nleft, and someone whose contract has not started yet, is left out whatever the scope\ntype, including a hand-picked `employees` selection. The schedule's `scope` still\nechoes the raw selection, so an edit form can round-trip what was picked.\n\nThe department is the one on the employee's most recent contract, supplied so a\npicker can group or label its options when the schedule spans more than one\ndepartment. Both department fields are null for an employee whose contract carries\nno department, which is normal for a company-scoped schedule.\n","required":["id","fullName","departmentId","departmentName"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the employee.","example":"550e8400-e29b-41d4-a716-446655440010"},"fullName":{"type":"string","description":"Display name of the employee, ordered according to the tenant's first-name or last-name-first preference.\n","example":"Jane Smith"},"departmentId":{"type":["string","null"],"format":"uuid","description":"Identifier of the department on the employee's most recent contract. Null when that contract carries no department.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"departmentName":{"type":["string","null"],"description":"Display name of the department on the employee's most recent contract. Null when that contract carries no department.\n","example":"Customer Support"}}}},"daysOfWeek":{"type":"array","description":"Weekdays covered by this schedule, stored as ISO 8601 weekday numbers\n(1 = Monday through 7 = Sunday). Returned as an empty array when no days\nare configured.\n","items":{"type":"integer","format":"int32","enum":[1,2,3,4,5,6,7],"description":"ISO 8601 weekday number (1 = Monday, 7 = Sunday).","example":1},"example":[1,2,3,4,5]},"dayStartTime":{"type":["string","null"],"description":"Start of the daily working window in `HH:MM` 24-hour format (local\nwall-clock, no timezone). Null when no start time is configured.\n","example":"09:00"},"dayEndTime":{"type":["string","null"],"description":"End of the daily working window in `HH:MM` 24-hour format (local\nwall-clock, no timezone). Null when no end time is configured.\n","example":"17:30"},"slotDurationMinutes":{"type":"integer","format":"int32","description":"Length in minutes of each bookable slot within the daily window. Defaults\nto the configured Tempus slot duration (typically 30) when not set.\n","example":30},"status":{"type":["object","null"],"description":"Default status assigned to entries generated from this schedule. Only\npresent when the `status` relation is eager-loaded; null when loaded but\nno default status is set, and omitted entirely when the relation is not\nloaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the status.","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","description":"Display name of the status.","example":"Available"}}},"subStatus":{"type":["object","null"],"description":"Default sub-status assigned to entries generated from this schedule. Only\npresent when the `subStatus` relation is eager-loaded; null when loaded\nbut no default sub-status is set, and omitted entirely when the relation\nis not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":"string","description":"Display name of the sub-status.","example":"On Break"}}},"statusFilters":{"type":"array","description":"Identifiers of the statuses that are selectable on this schedule's grid.\nUsed to restrict which statuses planners may apply. Returned as an empty\narray when no filter is configured (all statuses allowed).\n","items":{"type":"string","format":"uuid","description":"Identifier of an allowed status.","example":"550e8400-e29b-41d4-a716-446655440002"},"example":["550e8400-e29b-41d4-a716-446655440002","550e8400-e29b-41d4-a716-446655440003"]},"isActive":{"type":"boolean","description":"Whether the schedule is active. Inactive schedules are retained but not\nused to generate new planning entries.\n","example":true},"createdAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp when the schedule was created.","example":"2024-03-01T08:29:07+00:00","readOnly":true},"updatedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp when the schedule was last updated.","example":"2024-03-01T08:29:07+00:00","readOnly":true}}},"TempusScheduleCalendar":{"type":"object","description":"Weekly calendar view of a Tempus schedule, returned by the\n`GET \/{pbx_id}\/schedules\/{schedule}\/calendar` endpoint. The payload expands the\nschedule's recurring slots and their booked entries across a single week,\nproducing a ready-to-render grid for the planning UI.\n\nThis object documents the exact keys returned by the calendar builder, not the\nraw database columns. The week always begins on a Monday: when no `week_start`\nquery parameter is supplied it defaults to the Monday of the current week. The\n`days` array contains one entry per active weekday of the schedule (driven by\nthe schedule's `days_of_week`), and each day carries the slots that recur on\nthat date together with any entry booked into them.\n\nNote that the keys here use camelCase (for example `weekStart`, `dayLabel`,\n`columnIndex`), unlike the snake_case keys of the schedule object nested under\n`schedule`. All times are local wall-clock values formatted as `HH:MM` with no\ntimezone component, interpreted in the application timezone.\n","required":["schedule","weekStart","weekEnd","days"],"properties":{"schedule":{"type":"object","description":"The schedule this calendar belongs to, serialized as a `ScheduleResource`\nwith its `department`, `status`, and `subStatus` relations eager-loaded.\nSee the TempusScheduleManagement schema for full field documentation.\n"},"weekStart":{"type":"string","format":"date","description":"First day of the rendered week (always a Monday), as an ISO `YYYY-MM-DD`\ndate. Matches the supplied `week_start` parameter when provided, otherwise\nthe Monday of the current week.\n","example":"2024-03-04"},"weekEnd":{"type":"string","format":"date","description":"Last day of the rendered week as an ISO `YYYY-MM-DD` date. Derived from the\nhighest active weekday in the schedule's `days_of_week`, so it is not\nnecessarily the following Sunday.\n","example":"2024-03-08"},"days":{"type":"array","description":"One element per active weekday of the schedule within this week, ordered by\nweekday. Days on which the schedule is not active are omitted entirely.\n","items":{"type":"object","required":["date","dayLabel","isToday","slots"],"properties":{"date":{"type":"string","format":"date","description":"Calendar date of this day as an ISO `YYYY-MM-DD` value.","example":"2024-03-04"},"dayLabel":{"type":"string","description":"Human-readable label for the day, formatted as a localized short\nweekday name followed by the date (`ddd DD.MM.YYYY`).\n","example":"Mon 04.03.2024"},"isToday":{"type":"boolean","description":"Whether this day is the current date in the application timezone.","example":false},"slots":{"type":"array","description":"Slot occurrences that recur on this day, sorted by column index then\nstart time. A slot with no bookings appears once with a null `entry`;\na slot with multiple bookings appears once per booked entry.\n","items":{"type":"object","required":["slotId","renderKey","columnIndex","startTime","endTime","recurrenceType","recurrenceDays","recurrenceStartDate","recurrenceEndDate","entry"],"properties":{"slotId":{"type":"string","format":"uuid","description":"Identifier of the schedule slot this cell represents.","example":"550e8400-e29b-41d4-a716-446655440000"},"renderKey":{"type":"string","description":"Stable key for client-side rendering and reconciliation. For an\nunbooked slot it is `{slotId}:empty:{date}`; for a booked slot it\nis `{slotId}:{entryId}`.\n","example":"550e8400-e29b-41d4-a716-446655440000:550e8400-e29b-41d4-a716-446655440010"},"columnIndex":{"type":"integer","format":"int32","description":"Zero-based column the slot occupies in the grid, used to lay out\noverlapping slots side by side.\n","example":0},"startTime":{"type":"string","description":"Slot start time as `HH:MM`. For an exception entry (a moved\nbooking) this reflects the entry's actual start time rather than\nthe slot's nominal start.\n","example":"09:00"},"endTime":{"type":"string","description":"Slot end time as `HH:MM`. For an exception entry this reflects\nthe entry's actual end time rather than the slot's nominal end.\n","example":"17:00"},"recurrenceType":{"type":"string","enum":["none","daily","weekly","custom"],"description":"Recurrence rule governing on which dates the slot appears.","example":"weekly"},"recurrenceDays":{"type":["array","null"],"description":"Weekday numbers the slot recurs on for `weekly` and `custom`\nrecurrence. Null for `none` and `daily` recurrence.\n","items":{"type":"integer","format":"int32","description":"ISO weekday number (1 = Monday through 7 = Sunday).","example":1},"example":[1,2,3,4,5]},"recurrenceStartDate":{"type":["string","null"],"format":"date","description":"First date from which the slot's recurrence applies, as an ISO\n`YYYY-MM-DD` value, or null when unbounded.\n","example":"2024-01-01"},"recurrenceEndDate":{"type":["string","null"],"format":"date","description":"Last date on which the slot's recurrence applies, as an ISO\n`YYYY-MM-DD` value, or null when the recurrence has no end date.\n","example":"2024-12-31"},"entry":{"type":["object","null"],"description":"The booking occupying this slot on this date, or null when the\nslot is unbooked for the day.\n","required":["entryId","employeeId","userName","color","comment","isException"],"properties":{"entryId":{"type":"string","format":"uuid","description":"Identifier of the schedule entry (booking).","example":"550e8400-e29b-41d4-a716-446655440010"},"employeeId":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee assigned to the slot.","example":"550e8400-e29b-41d4-a716-446655440020"},"userName":{"type":["string","null"],"description":"Full name of the assigned employee for display, or null when\nthe employee record cannot be resolved.\n","example":"Jane Smith"},"color":{"type":"string","description":"Hex color assigned to this employee within the schedule, used\nto tint their entries on the grid. Assigned automatically on\nfirst use if not already set.\n","example":"#4F46E5"},"comment":{"type":["string","null"],"description":"Optional free-form note attached to the booking.","example":"Covering the morning desk"},"isException":{"type":"boolean","description":"Whether this entry deviates from the slot's recurring times\n(for example after being moved). When true the cell's\n`startTime` and `endTime` reflect the entry's own times.\n","example":false}}}}}}}}}}},"TempusScheduleEmployee":{"type":"object","description":"One assignable person of a schedule: an employee the schedule's scope covers and\nwho may therefore be booked into its slots.\n\nOnly employees holding a contract that is active today are listed \u2014 someone who has\nleft, and someone whose contract has not started yet, is left out whatever the scope\ntype, including a hand-picked `employees` selection. The schedule's `scope` still\nechoes the raw selection, so an edit form can round-trip what was picked.\n\nThe department is the one on the employee's most recent contract, supplied so a\npicker can group or label its options when the schedule spans more than one\ndepartment. Both department fields are null for an employee whose contract carries\nno department, which is normal for a company-scoped schedule.\n","required":["id","fullName","departmentId","departmentName"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the employee.","example":"550e8400-e29b-41d4-a716-446655440010"},"fullName":{"type":"string","description":"Display name of the employee, ordered according to the tenant's first-name or last-name-first preference.\n","example":"Jane Smith"},"departmentId":{"type":["string","null"],"format":"uuid","description":"Identifier of the department on the employee's most recent contract. Null when that contract carries no department.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"departmentName":{"type":["string","null"],"description":"Display name of the department on the employee's most recent contract. Null when that contract carries no department.\n","example":"Customer Support"}}},"TempusScheduleEntry":{"type":"object","description":"A single Tempus schedule entry: one assignment of an employee to a time slot\nwithin a published schedule, as serialized by `EntryResource`. An entry pins a\nconcrete start and end datetime, an optional comment, and a display colour\nresolved from the employee's per-schedule colour mapping.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The `employee` and `assignedBy` objects are relationship\nsummaries that are only present when their relation is eager-loaded on the\nmodel. When the relation is loaded but the related record is missing they are\nreturned as null, and when the relation is not loaded the key is omitted from\nthe payload entirely; integrators should treat both as \"no data available\".\n\nThe `color` value is a computed accessor (`color_hex`) looked up from the\nemployee's colour assignment for this schedule, so it can be null when no\ncolour has been configured.\n","required":["id","slotId","scheduleId","color","startDatetime","endDatetime","comment","isException","assignedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the schedule entry.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"slotId":{"type":"string","format":"uuid","description":"Identifier of the schedule slot (the recurring template position) this\nentry was generated from or assigned to.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"scheduleId":{"type":"string","format":"uuid","description":"Identifier of the parent schedule this entry belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"employee":{"type":["object","null"],"description":"Summary of the employee assigned to this entry. Only present when the\n`employee` relation is loaded; returned as null when the relation is\nloaded but the employee record cannot be resolved, and omitted entirely\nwhen the relation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the assigned employee.","example":"550e8400-e29b-41d4-a716-446655440003"},"fullName":{"type":"string","description":"Display name of the assigned employee.","example":"Jane Smith"}}},"color":{"type":["string","null"],"description":"Hex colour code used to display this entry, resolved from the employee's\ncolour assignment for this schedule. Null when no colour has been\nconfigured for the employee in this schedule. Read-only computed value.\n","readOnly":true,"example":"#3B82F6"},"startDatetime":{"type":["string","null"],"format":"date-time","description":"Start of the entry as an ISO 8601 datetime with timezone offset. Null when\nthe start has not been set.\n","example":"2024-03-01T08:00:00+00:00"},"endDatetime":{"type":["string","null"],"format":"date-time","description":"End of the entry as an ISO 8601 datetime with timezone offset. Null when\nthe end has not been set.\n","example":"2024-03-01T16:30:00+00:00"},"comment":{"type":["string","null"],"description":"Optional free-form note attached to this entry.","example":"Covering the morning reception shift"},"isException":{"type":"boolean","description":"Whether this entry is an exception (a manual override) rather than an\nentry generated from the recurring slot template.\n","example":false},"assignedBy":{"type":["object","null"],"description":"Summary of the user who created this assignment. Only present when the\n`assignedBy` relation is loaded; returned as null when the relation is\nloaded but the user cannot be resolved, and omitted entirely when the\nrelation is not loaded.\n","properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the user who made the assignment.","example":"550e8400-e29b-41d4-a716-446655440004"},"name":{"type":"string","description":"Display name of the user who made the assignment.","example":"Customer Support"}}},"assignedAt":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp with timezone offset for when the entry was assigned.\nNull when no assignment time has been recorded.\n","example":"2024-03-01T07:45:12+00:00"}}},"TempusScheduleSlot":{"type":"object","description":"A single recurring time slot belonging to a Tempus schedule, as serialized by\nthe `SlotResource`. A slot defines a daily start and end time together with a\nrecurrence rule (which days it repeats on and over what date range) and a\ncolumn position used to lay out overlapping slots side by side in the schedule\ngrid. Schedule entries (the concrete occurrences worked against the slot) are\nattached through the related `TempusScheduleEntry` records and are not embedded\nin this object.\n\nThis object documents the exact keys returned by the resource, not the raw\ndatabase columns. The `createdBy` field is only present when the `createdBy`\nrelation has been eager-loaded on the model; when it is loaded it is a compact\nobject (or null), and when it is not loaded the key is omitted entirely.\n\nTimes are returned trimmed to `HH:MM` (seconds removed). The recurrence date\nfields are returned as plain `YYYY-MM-DD` calendar dates without a time\ncomponent.\n","required":["id","scheduleId","columnIndex","startTime","endTime","recurrenceType","recurrenceDays","recurrenceStartDate","recurrenceEndDate","recurrenceCount","isActive"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the schedule slot.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"scheduleId":{"type":"string","format":"uuid","description":"Identifier of the parent Tempus schedule this slot belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"columnIndex":{"type":"integer","format":"int32","description":"Zero-based column position used to render the slot in the schedule grid.\nOverlapping active slots receive distinct column indices so they can be\ndisplayed side by side; the lowest free index is assigned automatically.\n","example":0},"startTime":{"type":"string","description":"Daily start time of the slot in 24-hour `HH:MM` form. Seconds are trimmed\nfrom the stored value before serialization.\n","example":"09:00"},"endTime":{"type":"string","description":"Daily end time of the slot in 24-hour `HH:MM` form. Seconds are trimmed\nfrom the stored value before serialization.\n","example":"17:30"},"recurrenceType":{"type":"string","enum":["daily","weekly","monthly","none"],"description":"Recurrence frequency rule that governs how the slot repeats. Determines\nhow `recurrenceDays`, `recurrenceEndDate` and `recurrenceCount` are\ninterpreted.\n","example":"weekly"},"recurrenceDays":{"type":["array","null"],"description":"Days the slot recurs on, used together with `recurrenceType`. For a weekly\nrecurrence these are ISO weekday numbers (1 = Monday through 7 = Sunday);\nfor a monthly recurrence they are days of the month. Null when no specific\ndays apply to the recurrence rule.\n","items":{"type":"integer","format":"int32","example":1},"example":[1,2,3,4,5]},"recurrenceStartDate":{"type":["string","null"],"format":"date","description":"First calendar date on which the slot recurrence becomes active, in\n`YYYY-MM-DD` form. Null when no start date is set.\n","example":"2024-03-01"},"recurrenceEndDate":{"type":["string","null"],"format":"date","description":"Last calendar date on which the slot recurrence remains active, in\n`YYYY-MM-DD` form. Null for an open-ended recurrence or when the\nrecurrence is instead bounded by `recurrenceCount`.\n","example":"2024-12-31"},"recurrenceCount":{"type":["integer","null"],"format":"int32","description":"Number of occurrences after which the recurrence ends. Null when the\nrecurrence is open-ended or bounded by `recurrenceEndDate` instead of a\nfixed count.\n","example":12},"isActive":{"type":"boolean","description":"Whether the slot is currently active. Inactive slots are retained but are\nexcluded from grid layout and column-index assignment.\n","example":true},"createdBy":{"type":["object","null"],"description":"Compact reference to the user who created the slot. Only present when the\n`createdBy` relation is eager-loaded; the key is omitted otherwise. Null\nwhen the relation is loaded but no creating user is associated.\n","readOnly":true,"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the user who created the slot.","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","description":"Display name of the user who created the slot.","example":"Customer Support"}}}}}}},"security":[{"bearerAuth":[]}],"tags":[{"name":"Auth","x-displayName":"Authentication","description":"Every endpoint uses **bearer token** authentication: send your token in the `Authorization` header on every request:\n\n```\nAuthorization: Bearer <token>\n```\n\nThere are two kinds of token:\n\n- **User token** - obtained by calling `POST \/login` with a user's credentials. It inherits that user's permissions and is scoped to their PBX(es). There is no separate \"global\" token; broader access comes from logging in as a user with broader role assignments (e.g. a super-admin).\n- **PBX API key** - created by the customer on the Cockpit **Integrations** page (an \"API key\" integration). It is owned by the PBX and limited to the scopes selected when the key was created.\n\nBoth kinds authenticate against the same endpoints. **Which fields a response contains can depend on the token type:** a few *per-user* fields are returned for user tokens and omitted for PBX API keys (see **Principal-conditional fields** above, and the `PRINCIPAL-CONDITIONAL` note on the affected fields).\n\nPer-operation auth requirements are listed under each endpoint's **Security** section.\n"},{"name":"AiConfiguration","x-displayName":"AI configuration","description":"Read-only aggregated AI setup for a PBX (global prompt, labels, keyword tree, per-extension and per-group prompts, AI profile and feature flags). Read with a PBX API key carrying the `ai-configuration` scope."},{"name":"CallerIdentities","x-displayName":"Caller Identities","description":"Caller identities represent the outbound phone numbers (and optional suffixes) available to the authenticated user when placing calls. Each identity is linked to a phone number and a target entity (User, PBX, Group, or SIP device)."},{"name":"Calls","x-displayName":"Calls","description":"Endpoints for initiating and managing outbound calls."},{"name":"CallFlows","x-displayName":"Call Flows","description":"Define how inbound calls are routed through your PBX. A call flow chains ordered steps (transfer, IVR, voicemail, queue, schedule) that the system evaluates per call."},{"name":"CallFlowSteps","x-displayName":"Call Flow Steps","description":"Individual steps belonging to a call flow. Each step has a type and a target (extension, queue, sound file, IVR, etc.) and is executed in order."},{"name":"Contacts","x-displayName":"Contacts","description":"Shared address book entries available across the PBX."},{"name":"ContactImports","x-displayName":"Contact Imports","description":"Import personal contacts from a CSV or Excel file via a guided upload, map, and confirm flow. Each import and every contact it creates is private to the authenticated user."},{"name":"Extensions","x-displayName":"Extensions","description":"Internal dial numbers assigned to users, devices, queues, and other PBX entities."},{"name":"Groups","x-displayName":"Groups","description":"Ring groups that dial multiple destinations simultaneously or in sequence."},{"name":"IVR","x-displayName":"IVR","description":"Interactive Voice Response menus that play a prompt and route the caller based on the key they press."},{"name":"IVR Steps","x-displayName":"IVR Steps","description":"Individual menu options inside an IVR. Each step maps a digit (or timeout) to a destination."},{"name":"Languages","x-displayName":"Languages","description":"Languages available for sound files, voice prompts, and user preferences."},{"name":"Locations","x-displayName":"Locations","description":"Physical offices or sites associated with the PBX, used for emergency call routing and reporting."},{"name":"Numbers","x-displayName":"Phone Number Orders","description":"Customer-facing endpoints for the Nexus number-order proxy. Use these to\ncheck whether a phone number can be provisioned at a given address, place\nan order (with KYC documents attached), retrieve an order's status, edit\nand retry an order that failed submission, list the phone numbers already\nowned by the PBX, and attach a call flow to a specific number.\n\nAuthentication is the PBX API key (one token per PBX); every response is\nscoped to that PBX.\n"},{"name":"Push configuration","x-displayName":"Push configuration","description":"Push the PBX configuration so pending changes take effect - the programmatic equivalent of the \"Push configuration\"\nbutton in Cockpit. PBX API key auth; rate limited to 1 request\/minute per PBX.\n"},{"name":"OdooInstaller","x-displayName":"Odoo Installer","description":"Endpoints consumed by the Voxbi Installer module running inside a customer's Odoo.\nRegister the Odoo integration, poll the install status, read it back, and update or\nre-run it. Authenticated with a customer API key carrying the `odoo-installer`\nability; the PBX is resolved from the key.\n"},{"name":"Pbxes","x-displayName":"Pbxes","description":"The tenant container. Every other resource is scoped to a PBX."},{"name":"PhoneNumbers","x-displayName":"Phone Numbers","description":"External DIDs owned by the PBX. Numbers are linked to call flows, users, or queues for inbound routing."},{"name":"Queues","x-displayName":"Queues","description":"Call queues that hold callers until an agent is available, with configurable strategies and music on hold."},{"name":"SipCarriers","x-displayName":"SIP Carriers","description":"Upstream SIP trunks used for outbound calls and number termination."},{"name":"SipDevices","x-displayName":"SIP Devices","description":"Physical or soft SIP endpoints (deskphones, softphones, ATAs) registered against the PBX."},{"name":"SoundFiles","x-displayName":"Sound Files","description":"Audio files used for greetings, prompts, music on hold, and voicemail."},{"name":"Statuses","x-displayName":"Statuses","description":"Top-level presence values (e.g. Available, Busy, Away) that users can broadcast."},{"name":"Substatuses","x-displayName":"Substatuses","description":"Refinements under a parent status (e.g. Away > Lunch, Away > Meeting)."},{"name":"Tags","x-displayName":"Tags","description":"Free-form labels attached to users, devices, or numbers for filtering and reporting."},{"name":"Schedules","x-displayName":"Schedules","description":"Time-of-day rule sets used by call flows to route differently inside vs outside business hours."},{"name":"Twinning","x-displayName":"Twinning","description":"Ring an external number in parallel with the user's extension."},{"name":"DND","x-displayName":"Do Not Disturb","description":"Manage Do Not Disturb rules for users and extensions."},{"name":"Images","x-displayName":"Images","description":"Retrieve images (avatars, logos) associated with models."},{"name":"UserGroups","x-displayName":"User Groups","description":"Manage user groups for organizing users within a PBX."},{"name":"Pools","x-displayName":"Pools","description":"Extension pools and their user assignments."},{"name":"VoxbiGroupTabs","x-displayName":"Voxbi Group Tabs","description":"Custom tab configurations for Voxbi group views."},{"name":"Users","x-displayName":"Users","description":"PBX users. Each user owns an extension, devices, presence status, and forwarding rules."},{"name":"Webhooks","x-displayName":"Webhooks","description":"Inbound webhooks from third-party services (e.g. Famulor post-call events)."},{"name":"CDRs","x-displayName":"CDR Utility","description":"### CDR Utility Proxy\n\nForwards authenticated requests to the internal CDRs API. Rate-limited to 120 requests\/minute per user.\n\nBase URL: `\/api\/v1\/cdrs-utility\/`\n"},{"name":"TempusAbsences","x-displayName":"Absences","description":"Employee absence requests, absence records, and validator decisions on them."},{"name":"TempusHomeOffice","x-displayName":"Home office","description":"Home office requests, home office calendars, and validator decisions on them."},{"name":"TempusCorrections","x-displayName":"Corrections","description":"Time point correction requests and validator decisions on them."},{"name":"TempusOvertime","x-displayName":"Overtime","description":"Overtime calculation periods and per-employee overtime decisions."},{"name":"TempusWorkTimes","x-displayName":"Work times","description":"Weekly and required work times and compiled workshifts."},{"name":"TempusSchedules","x-displayName":"Schedules","description":"Managed work schedules, slots, and entry assignments."},{"name":"TempusCalendar","x-displayName":"Calendar","description":"Company and per-employee absence, home office, and personal calendars."},{"name":"TempusProfile","x-displayName":"Profile","description":"Employee profile, holidays reports, associated companies, and next availability."},{"name":"TempusReports","x-displayName":"Reports","description":"Worked-time reports and yearly summary totals per employee."},{"name":"TempusEmployees","x-displayName":"Employees","description":"Tempus employees, departments, and their time points."},{"name":"TempusValidators","x-displayName":"Validators","description":"Validator scope and validator-facing pending requests and corrections."},{"name":"TempusInternal","x-displayName":"Tempus terminals and recurring transactions","description":"Tempus endpoints for badge readers and NFC terminals (authenticated with a PBX API-key token carrying the `terminals` ability) and for managing recurring transactions (PBX API key)."},{"name":"v2","x-displayName":"API v2","description":"### API v2 Endpoints\n\nSecond-generation endpoints with improved response structures.\n\nBase URL: `\/api\/v2\/`\n"},{"name":"aiConfigurationModel","x-displayName":"AI configuration","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/AiConfiguration\" \/>"},{"name":"callerIdentityModel","x-displayName":"Caller Identity","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/CallerIdentity\" \/>"},{"name":"callFlowModel","x-displayName":"Call Flow","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/CallFlow\" \/>"},{"name":"callFlowStepModel","x-displayName":"Call Flow Step","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/CallFlowStep\" \/>"},{"name":"contactModel","x-displayName":"Contact","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Contact\" \/>"},{"name":"contactImportModel","x-displayName":"Contact Import","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/ContactImport\" \/>"},{"name":"extensionModel","x-displayName":"Extension","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Extension\" \/>"},{"name":"groupModel","x-displayName":"Group","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Group\" \/>"},{"name":"ivrModel","x-displayName":"IVR","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/IVR\" \/>"},{"name":"ivrStepModel","x-displayName":"IVR Step","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/IVRStep\" \/>"},{"name":"languageModel","x-displayName":"Language","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Language\" \/>"},{"name":"locationModel","x-displayName":"Location","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Location\" \/>"},{"name":"pbxModel","x-displayName":"Pbx","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Pbx\" \/>"},{"name":"phoneNumberModel","x-displayName":"Phone Number","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/PhoneNumber\" \/>"},{"name":"queueModel","x-displayName":"Queue","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Queue\" \/>"},{"name":"sipCarrierModel","x-displayName":"Sip Carrier","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/SipCarrier\" \/>"},{"name":"sipDeviceModel","x-displayName":"Sip Device","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/SipDevice\" \/>"},{"name":"soundFileModel","x-displayName":"Sound File","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/SoundFile\" \/>"},{"name":"statusModel","x-displayName":"Status","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Status\" \/>"},{"name":"subStatusModel","x-displayName":"Substatus","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Substatus\" \/>"},{"name":"tagModel","x-displayName":"Tag","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Tag\" \/>"},{"name":"scheduleModel","x-displayName":"Schedule","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Schedule\" \/>"},{"name":"twinningModel","x-displayName":"Twinning","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Twinning\" \/>"},{"name":"userModel","x-displayName":"User","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/User\" \/>"},{"name":"inCallStateModel","x-displayName":"InCallState","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/InCallState\" \/>"},{"name":"Metadata","x-displayName":"Metadata","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Metadata\" \/>"},{"name":"Links","x-displayName":"Links","description":"<SchemaDefinition schemaRef=\"#\/components\/schemas\/Links\" \/>"}],"x-tagGroups":[{"name":"Telephony","tags":["Auth","AiConfiguration","Calls","CallFlows","CallFlowSteps","IVR","IVR Steps","Queues","Schedules","PhoneNumbers","CallerIdentities","SipCarriers","SipDevices","Extensions","Twinning","DND","Users","UserGroups","Groups","Pools","Tags","Statuses","Substatuses","VoxbiGroupTabs","Pbxes","Locations","Languages","SoundFiles","Contacts","ContactImports","Images","SmartIvr","Webhooks","UserProvisioning","DirectLogin","PbxServerApi","Roaming","sts","Numbers","Push configuration","OdooInstaller"]},{"name":"Tempus","tags":["TempusAbsences","TempusHomeOffice","TempusCorrections","TempusOvertime","TempusWorkTimes","TempusSchedules","TempusCalendar","TempusProfile","TempusReports","TempusEmployees","TempusValidators","TempusInternal"]},{"name":"Partner","tags":["Partner"]},{"name":"API v2","tags":["v2"]},{"name":"CDRs","tags":["CDRs"]},{"name":"Models","tags":["aiConfigurationModel","callerIdentityModel","callFlowModel","callFlowStepModel","contactModel","contactImportModel","extensionModel","groupModel","ivrModel","ivrStepModel","languageModel","locationModel","pbxModel","phoneNumberModel","queueModel","sipCarrierModel","sipDeviceModel","soundFileModel","statusModel","subStatusModel","tagModel","scheduleModel","twinningModel","userModel","inCallStateModel","Metadata","Links"]}],"paths":{"\/login":{"post":{"security":[],"tags":["Auth"],"summary":"Log in with email and password (public)","operationId":"postAuthLogin","description":"Authenticates a user with email and password and returns a personal access token used as the Bearer credential on every subsequent request.","x-codeSamples":[{"lang":"curl","label":"cURL","source":"curl -X POST 'https:\/\/cockpit.voxbi.com\/api\/v1\/login' \\\n  -H 'Accept: application\/json' \\\n  -H 'Content-Type: application\/json' \\\n  -d '{\n    \"email\": \"user@example.com\",\n    \"password\": \"strongPassword\"\n  }'\n"},{"lang":"JavaScript","label":"JavaScript (fetch)","source":"const res = await fetch('https:\/\/cockpit.voxbi.com\/api\/v1\/login', {\n  method: 'POST',\n  headers: {\n    'Accept': 'application\/json',\n    'Content-Type': 'application\/json',\n  },\n  body: JSON.stringify({\n    email: 'user@example.com',\n    password: 'strongPassword',\n  }),\n});\nconst { data } = await res.json();\nconst token = data.token;\n"},{"lang":"PHP","label":"PHP (Guzzle)","source":"$client = new GuzzleHttp\\Client();\n$response = $client->post('https:\/\/cockpit.voxbi.com\/api\/v1\/login', [\n    'headers' => ['Accept' => 'application\/json'],\n    'json' => [\n        'email' => 'user@example.com',\n        'password' => 'strongPassword',\n    ],\n]);\n$token = json_decode($response->getBody())->data->token;\n"},{"lang":"Python","label":"Python (requests)","source":"import requests\n\nres = requests.post(\n    'https:\/\/cockpit.voxbi.com\/api\/v1\/login',\n    headers={'Accept': 'application\/json'},\n    json={'email': 'user@example.com', 'password': 'strongPassword'},\n)\ntoken = res.json()['data']['token']\n"}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password"}}},"example":{"email":"user@example.com","password":"strongPassword"}}}},"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"data":{"type":"object","properties":{"token":{"type":"string","description":"Personal access token to send in the Authorization header as a Bearer credential on subsequent requests."}}}}},"example":{"message":"User Logged In Successfully","data":{"token":"2|BeLWgqvfWsJTftMZ8mp2LGKdTUUCYb1HpFQJciEjb96187d8"}}}}},"401":{"description":"Invalid email or password.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Invalid email or password."}}}},"403":{"description":"The user account is disabled.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"User is not active."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/me":{"get":{"tags":["Auth"],"summary":"Get the authenticated user (user)","operationId":"getAuthMe","description":"Returns the currently authenticated user's profile data including extensions, SIP devices, groups, twinnings, and integrations. Requires a user-owned bearer token.","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"pbx_id":{"type":"string"},"full_name_with_email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string","format":"email"},"language":{"type":"string"},"access_token":{"type":["string","null"]},"email_verified_at":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"allow_telephony":{"type":"boolean"},"allow_dnd":{"type":"boolean"},"allow_change_twinning_dest":{"type":"boolean"},"allow_call_forwarding":{"type":"boolean"},"allow_manage_global_contacts":{"type":"boolean"},"call_recordings_visibility":{"type":["string","null"]},"extension_roaming":{"type":"boolean"},"call_information_visibility":{"type":["string","null"]},"allow_status_changer":{"type":"boolean"},"allow_manage_voicemail_parameters":{"type":"boolean"},"show_in_address_book":{"type":"boolean"},"voicemail_type":{"type":["string","null"]},"voicemail_destination":{"type":["string","null"]},"concurrent_calls":{"type":["integer","null"]},"vip":{"type":"boolean"},"sync_source":{"type":["string","null"]},"allow_anonymous_calls":{"type":"boolean"},"identity_provider_uid":{"type":["string","null"]},"is_shadow":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"webrtc_configuration":{"type":["object","null"]},"extensions":{"type":"array","items":{"type":"object"}},"sipDevices":{"type":"array","items":{"type":"object"}},"groups":{"type":"array","items":{"type":"object"}},"twinnings":{"type":"array","items":{"type":"object"}},"caller_identities":{"type":"array","items":{"type":"object"}},"integrations":{"type":"array","items":{"type":"object"}},"pbx":{"type":"object"},"microsoft":{"type":"object","properties":{"fetch_contacts":{"type":"boolean"}}},"odoo":{"type":"object","properties":{"fetch_contacts":{"type":"boolean"}}},"employee_id":{"type":["string","null"],"format":"uuid"},"tempus":{"type":["string","null"]}}}}},"example":{"message":"Success","data":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"pbx-123","full_name_with_email":"John Doe (john.doe@example.com)","first_name":"John","last_name":"Doe","email":"john.doe@example.com","language":"en","access_token":null,"email_verified_at":"2023-01-01T00:00:00.000000Z","status":"active","allow_telephony":true,"allow_dnd":true,"allow_change_twinning_dest":false,"allow_call_forwarding":true,"allow_manage_global_contacts":false,"call_recordings_visibility":null,"extension_roaming":false,"call_information_visibility":null,"allow_status_changer":true,"allow_manage_voicemail_parameters":false,"show_in_address_book":true,"voicemail_type":null,"voicemail_destination":null,"concurrent_calls":null,"vip":false,"sync_source":null,"allow_anonymous_calls":false,"identity_provider_uid":null,"is_shadow":false,"created_at":"2023-01-01T00:00:00.000000Z","updated_at":"2023-10-12T12:25:52.000000Z","webrtc_configuration":null,"extensions":[],"sipDevices":[],"groups":[],"twinnings":[],"caller_identities":[],"integrations":[],"pbx":[],"microsoft":{"fetch_contacts":false},"odoo":{"fetch_contacts":false},"employee_id":null,"tempus":null}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/user":{"get":{"tags":["Auth"],"summary":"Get the authenticated user record (user)","operationId":"getAuthUserRecord","description":"Returns the raw authenticated user model (the owner of the Sanctum token). This is a\nthin endpoint that serialises the user record directly; for the assembled profile with\nextensions, SIP devices, groups, twinnings and integrations use `GET \/me` instead.\nHidden attributes (password, tokens) are never serialised.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"pbx_id":{"type":"string","format":"uuid"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string","format":"email"},"status":{"type":"string"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","first_name":"John","last_name":"Doe","email":"john.doe@example.com","status":"active","created_at":"2026-01-01T00:00:00+00:00","updated_at":"2026-06-01T12:25:52+00:00"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/magic-login\/{token}":{"get":{"tags":["Auth"],"summary":"Log in with a magic link token","operationId":"getAuthMagicLogin","description":"Authenticates a user via a magic link token. Returns a redirect or JSON response on success.","security":[],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"},{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"The magic link token sent to the user's email.","example":"abc123def456ghi789"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"data":{"type":"object","properties":{"token":{"type":"string"}}}}},"example":{"message":"User Logged In Successfully","data":{"token":"2|BeLWgqvfWsJTftMZ8mp2LGKdTUUCYb1HpFQJciEjb96187d8"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/passwordless\/login":{"post":{"tags":["Auth"],"summary":"Request Passwordless Login Code","operationId":"postAuthPasswordlessLogin","description":"Sends a one-time login code to the provided email address. The code expires after a configured timeout.","security":[],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}},"example":{"email":"user@example.com"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"expires_in":{"type":"integer","description":"Number of seconds until the code expires."}}},"example":{"success":true,"expires_in":900}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/passwordless\/verify":{"post":{"tags":["Auth"],"summary":"Verify Passwordless Login Code","operationId":"postAuthPasswordlessVerify","description":"Verifies a one-time login code for the given email and returns an auth token on success.","security":[],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["email","code"],"properties":{"email":{"type":"string","format":"email"},"code":{"type":"string","description":"The 6-digit one-time login code sent to the user's email.","minLength":6,"maxLength":6}}},"example":{"email":"user@example.com","code":"123456"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"data":{"type":"object","properties":{"token":{"type":"string"}}}}},"example":{"message":"User Logged In Successfully","data":{"token":"2|BeLWgqvfWsJTftMZ8mp2LGKdTUUCYb1HpFQJciEjb96187d8"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/passwordless\/resend":{"post":{"tags":["Auth"],"summary":"Resend Passwordless Login Code","operationId":"postAuthPasswordlessResend","description":"Resends a one-time login code to the provided email address, subject to a cooldown period.","security":[],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}},"example":{"email":"user@example.com"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"expires_in":{"type":"integer","description":"Number of seconds until the new code expires."}}},"example":{"success":true,"expires_in":900}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/request-password-reset":{"post":{"tags":["Auth"],"summary":"Request a password reset email","operationId":"postAuthRequestPasswordReset","description":"Sends a password reset email to the provided address. Requires HPP API key authentication.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}},"example":{"email":"user@example.com"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Password reset email sent successfully."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/reset-password":{"post":{"tags":["Auth"],"summary":"Reset Password","operationId":"postAuthResetPassword","description":"Resets the user's password using a valid reset token. Requires HPP API key authentication.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["token","password"],"properties":{"token":{"type":"string","description":"The password reset token received by email."},"password":{"type":"string","format":"password","description":"The new password to set."}}},"example":{"token":"abc123def456ghi789jkl012mno345pqr","password":"newStrongPassword123"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Password has been reset successfully."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/edit-password":{"post":{"tags":["Auth"],"summary":"Set a new password","operationId":"postAuthEditPassword","description":"Changes the authenticated user's password by verifying the old password and setting a new one. Requires HPP API key authentication.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["old_password","new_password"],"properties":{"old_password":{"type":"string","format":"password","description":"The user's current password."},"new_password":{"type":"string","format":"password","description":"The new password to set."}}},"example":{"old_password":"currentPassword123","new_password":"newStrongPassword456"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Password updated successfully."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/caller-identities":{"get":{"tags":["CallerIdentities"],"summary":"List Caller Identities for the authenticated user","operationId":"listCallerIdentities","description":"Returns a paginated list of caller identities. Use the standard `search`, `sort`, `page`,\nand `perPage` query parameters; use `filter[key]=value` to narrow the result set.\nMulti-tenant scoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"An outbound caller identity: the phone number (plus optional suffix and label)\nshown to the called party when this entity places a call. Each identity is\nattached to exactly one target (`User`, `Pbx`, `Group`, or `SipDevice`).\nThis table has no `timestamps`.\n","required":["id","pbx_id","phone_number_id","caller_identity_target_type","caller_identity_target_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Caller identity identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"phone_number_id":{"type":"string","format":"uuid","description":"Identifier of the PhoneNumber used as the outbound CID","example":"550e8400-e29b-41d4-a716-446655440002"},"suffix":{"type":["string","null"],"description":"Optional digit suffix appended to the base phone number","example":"23"},"label":{"type":["string","null"],"description":"Human-readable label shown in the admin UI","example":"Sales line"},"caller_identity_target_type":{"type":"string","description":"Polymorphic morph class for the entity this identity is attached to.\nStored as a fully qualified PHP class name.\n","enum":["App\\Models\\User","App\\Models\\Pbx","App\\Models\\Group","App\\Models\\SipDevice"],"example":"App\\Models\\User"},"caller_identity_target_id":{"type":"string","format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"order":{"type":"integer","description":"Display order within the target's caller identity list","example":1}}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","phone_number_id":"550e8400-e29b-41d4-a716-446655440002","suffix":"23","label":"Sales line","caller_identity_target_type":"App\\Models\\User","caller_identity_target_id":"550e8400-e29b-41d4-a716-446655440003","order":1}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/caller-identities\/{id}":{"get":{"tags":["CallerIdentities"],"summary":"Get a caller Identity","operationId":"getCallerIdentity","description":"Returns the caller identity identified by the path parameter. Multi-tenant scoping is\nenforced: the caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true,"description":"UUID of the caller identity","example":"550e8400-e29b-41d4-a716-446655440000"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"An outbound caller identity: the phone number (plus optional suffix and label)\nshown to the called party when this entity places a call. Each identity is\nattached to exactly one target (`User`, `Pbx`, `Group`, or `SipDevice`).\nThis table has no `timestamps`.\n","required":["id","pbx_id","phone_number_id","caller_identity_target_type","caller_identity_target_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Caller identity identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"phone_number_id":{"type":"string","format":"uuid","description":"Identifier of the PhoneNumber used as the outbound CID","example":"550e8400-e29b-41d4-a716-446655440002"},"suffix":{"type":["string","null"],"description":"Optional digit suffix appended to the base phone number","example":"23"},"label":{"type":["string","null"],"description":"Human-readable label shown in the admin UI","example":"Sales line"},"caller_identity_target_type":{"type":"string","description":"Polymorphic morph class for the entity this identity is attached to.\nStored as a fully qualified PHP class name.\n","enum":["App\\Models\\User","App\\Models\\Pbx","App\\Models\\Group","App\\Models\\SipDevice"],"example":"App\\Models\\User"},"caller_identity_target_id":{"type":"string","format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"order":{"type":"integer","description":"Display order within the target's caller identity list","example":1}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","phone_number_id":"550e8400-e29b-41d4-a716-446655440002","suffix":"23","label":"Sales line","caller_identity_target_type":"App\\Models\\User","caller_identity_target_id":"550e8400-e29b-41d4-a716-446655440003","order":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/call-flows":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["CallFlows"],"summary":"List Call flow","operationId":"listCallFlows","description":"Returns a paginated list of call flows. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `enabled`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A named, ordered sequence of routing rules applied to inbound (and internal)\ncalls on a tenant. A CallFlow groups the individual routing steps that decide\nwhere a call goes (IVR menus, queues, extensions, schedules, voicemail, and so\non). This read-only API shape exposes the curated CallFlow header fields only:\nthe ordered step list, the internal checksum, and soft-delete timestamp are not\nreturned here.\n","required":["id","pbx_id","name","enabled","version"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique call flow identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this call flow.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Human-readable label for the call flow, shown in lists and pickers.","example":"Main inbound flow"},"description":{"type":["string","null"],"description":"Optional free-text note describing the purpose of the call flow.","example":"Routes incoming calls to support, then voicemail."},"enabled":{"type":"boolean","description":"Whether the call flow is active. Disabled flows are not applied to calls.","example":true},"version":{"type":["integer","null"],"format":"int32","minimum":0,"description":"Version counter for the call flow. Set to 1 when the flow is created and\nbumped on subsequent saves, allowing integrators to detect changes.\n","example":7},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["CallFlows"],"summary":"Create a call flow","operationId":"createCallFlow","description":"Create a call flow. Only `name`, `description` and `enabled` are accepted; the PBX is\ntaken from the authenticated token. Call flow steps are not part of this request: create\nthem separately against `\/call-flow-steps` once the call flow exists.\n","security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":255,"description":"Name of the call flow."},"description":{"type":["string","null"],"description":"Optional free-form description."},"enabled":{"type":"boolean","description":"Whether the call flow is active. Falls back to the model default when omitted."}}},"example":{"name":"Main inbound flow","description":"Routes incoming calls to support, then voicemail","enabled":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","description":"A named, ordered sequence of routing rules applied to inbound (and internal)\ncalls on a tenant. A CallFlow groups the individual routing steps that decide\nwhere a call goes (IVR menus, queues, extensions, schedules, voicemail, and so\non). This read-only API shape exposes the curated CallFlow header fields only:\nthe ordered step list, the internal checksum, and soft-delete timestamp are not\nreturned here.\n","required":["id","pbx_id","name","enabled","version"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique call flow identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this call flow.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Human-readable label for the call flow, shown in lists and pickers.","example":"Main inbound flow"},"description":{"type":["string","null"],"description":"Optional free-text note describing the purpose of the call flow.","example":"Routes incoming calls to support, then voicemail."},"enabled":{"type":"boolean","description":"Whether the call flow is active. Disabled flows are not applied to calls.","example":true},"version":{"type":["integer","null"],"format":"int32","minimum":0,"description":"Version counter for the call flow. Set to 1 when the flow is created and\nbumped on subsequent saves, allowing integrators to detect changes.\n","example":7},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/call-flows\/{call_flow}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["CallFlows"],"summary":"Get a Call flow","operationId":"getCallFlow","description":"Returns the call flow identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"A named, ordered sequence of routing rules applied to inbound (and internal)\ncalls on a tenant. A CallFlow groups the individual routing steps that decide\nwhere a call goes (IVR menus, queues, extensions, schedules, voicemail, and so\non). This read-only API shape exposes the curated CallFlow header fields only:\nthe ordered step list, the internal checksum, and soft-delete timestamp are not\nreturned here.\n","required":["id","pbx_id","name","enabled","version"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique call flow identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this call flow.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Human-readable label for the call flow, shown in lists and pickers.","example":"Main inbound flow"},"description":{"type":["string","null"],"description":"Optional free-text note describing the purpose of the call flow.","example":"Routes incoming calls to support, then voicemail."},"enabled":{"type":"boolean","description":"Whether the call flow is active. Disabled flows are not applied to calls.","example":true},"version":{"type":["integer","null"],"format":"int32","minimum":0,"description":"Version counter for the call flow. Set to 1 when the flow is created and\nbumped on subsequent saves, allowing integrators to detect changes.\n","example":7},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601) when the call flow was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/call-flow-steps":{"get":{"tags":["CallFlowSteps"],"summary":"List Call flow step","operationId":"listCallFlowSteps","description":"Returns a paginated list of call flow steps. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, pbx_id, call_flow_id, type, options, is_active and order.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"description":"A single step inside a call flow. Steps are evaluated in ascending `order`\nto drive how an inbound call is handled. The `type` field discriminates the\nshape of `options`: each variant below documents the keys carried in\n`options` for that particular step type. Variants with no configurable\nsettings (`hang_up`, `start_recording`, `answer`) use an empty options\nobject. The v1 API returns exactly these top-level fields on every variant:\n`id`, `pbx_id`, `call_flow_id`, `type`, `options`, `is_active`, `order`.\nMost ID references inside `options` are UUIDs of related resources (users,\ngroups, IVRs, queues, schedules, etc.) scoped to the same tenant.\n","oneOf":[{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ring_user)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ring_user"],"description":"Step type. For this variant it rings one or more cockpit users, SIP devices, or groups.","example":"ring_user"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings describing which targets to ring and for how long.","required":["duration"],"properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Ring duration in seconds before moving to the next step.","example":20},"also_ring_dialed_extension":{"type":"boolean","description":"When true, also rings the extension that was originally dialed.","example":false},"also_ring_everyone_in_the_user_group":{"type":"boolean","description":"When true, also rings every member of the dialed user's group.","example":false},"dial_mobile_twinnings":{"type":"boolean","description":"When true, also rings the mobile twinning numbers configured for the targets.","example":false},"missed_calls":{"type":"boolean","description":"When true, an unanswered call on this step counts as a missed call for the targets. Defaults to true.","example":true},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist played while ringing.","example":"550e8400-e29b-41d4-a716-446655440010"},"users":{"type":["array","null"],"description":"Identifiers of the users to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440011"]},"sip_devices":{"type":["array","null"],"description":"Identifiers of the SIP devices to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440012"]},"groups":{"type":["array","null"],"description":"Identifiers of the user groups to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440013"]},"tags":{"type":["array","null"],"description":"Identifiers of tags whose tagged users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440014"]},"locations":{"type":["array","null"],"description":"Identifiers of locations whose users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440015"]},"languages":{"type":["array","null"],"description":"Identifiers of languages used to select which users to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440016"]},"pools":{"type":["array","null"],"description":"Identifiers of pools whose users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440017"]},"statuses":{"type":["array","null"],"description":"Identifiers of Tempus statuses used to filter which users are rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440018"]},"pickup_lines":{"type":["array","null"],"description":"Identifiers of users whose calls may be picked up by this step.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440019"]},"sub_statuses":{"type":["object","null"],"description":"Map keyed by Tempus status UUID. Each value is the list of\nTempus sub-status UUIDs selected under that status.\n","additionalProperties":{"type":"array","items":{"type":"string","format":"uuid"}},"example":{"550e8400-e29b-41d4-a716-446655440018":["550e8400-e29b-41d4-a716-446655440020"]}}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ring_external_number)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ring_external_number"],"description":"Step type. For this variant it dials out to an external PSTN number.","example":"ring_external_number"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":1},"options":{"type":"object","description":"Settings describing the external number to dial.","properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Ring duration in seconds before moving to the next step.","example":30},"number":{"type":["string","null"],"description":"External destination number in E.164 format.","example":"+12125550100"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist played while ringing.","example":"550e8400-e29b-41d4-a716-446655440010"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (call_flow)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["call_flow"],"description":"Step type. For this variant it routes the call to another call flow or extension.","example":"call_flow"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":2},"options":{"type":"object","description":"Settings describing the destination and optional schedule.","required":["call_flow_or_extension"],"properties":{"call_flow_or_extension":{"type":"string","enum":["extension","call_flow"],"description":"Selects whether the call is routed to an extension or another call flow.","example":"call_flow"},"extension":{"type":["string","null"],"format":"uuid","description":"Identifier of the destination extension (used when routing to an extension).","example":"550e8400-e29b-41d4-a716-446655440030"},"call_flow":{"type":["string","null"],"format":"uuid","description":"Identifier of the destination call flow (used when routing to a call flow).","example":"550e8400-e29b-41d4-a716-446655440031"},"schedule":{"type":["string","null"],"format":"uuid","description":"Identifier of a schedule that gates when this routing applies.","example":"550e8400-e29b-41d4-a716-446655440032"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (go_to_ivr)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["go_to_ivr"],"description":"Step type. For this variant it hands the call off to an IVR menu.","example":"go_to_ivr"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying which IVR to enter.","properties":{"ivr":{"type":["string","null"],"format":"uuid","description":"Identifier of the IVR menu to enter.","example":"550e8400-e29b-41d4-a716-446655440040"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (enter_queue)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["enter_queue"],"description":"Step type. For this variant it parks the caller in a queue.","example":"enter_queue"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":1},"options":{"type":"object","description":"Settings identifying the queue and how long to wait.","properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Maximum time in seconds to keep the caller queued before moving on.","example":60},"queue":{"type":["string","null"],"format":"uuid","description":"Identifier of the queue to enter.","example":"550e8400-e29b-41d4-a716-446655440050"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (text_to_speech)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["text_to_speech"],"description":"Step type. For this variant it plays an announcement (sound file or synthesized speech).","example":"text_to_speech"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings describing the announcement source.","required":["announcement_type"],"properties":{"announcement_type":{"type":"string","enum":["sound_file","tts_tag","tts_message"],"description":"Selects the announcement source (a stored sound file, a TTS tag, or a free-text TTS message).","example":"tts_message"},"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the announcement sound file to play (used when announcement_type is sound_file).","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override. `null` (Auto) plays the variant for the\nlanguage detected\/inherited earlier in the call; otherwise an ISO-639-1 code\nforces that variant.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"tts_tag":{"type":["string","null"],"description":"Predefined TTS tag identifying a templated message (used when announcement_type is tts_tag).","example":"greeting_morning"},"tts_message":{"type":["string","null"],"description":"Free-text message to synthesize and play (used when announcement_type is tts_message).","example":"Welcome to Customer Support."}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (change_ringtone_and_label)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["change_ringtone_and_label"],"description":"Step type. For this variant it overrides the ringtone and the caller display label.","example":"change_ringtone_and_label"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings overriding ringtone, label, and music on hold.","properties":{"ringtone":{"type":["string","null"],"enum":["alert-ring1","alert-ring2","alert-ring3","alert-ring4","alert-ring5","null"],"description":"Ringtone key to apply on the receiving device.","example":"alert-ring1"},"label":{"type":["string","null"],"description":"Display label shown to the called party for the incoming call.","example":"VIP"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist to apply.","example":"550e8400-e29b-41d4-a716-446655440010"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (webhook)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["webhook"],"description":"Step type. For this variant it fires an outbound HTTP request mid-flow.","example":"webhook"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":2},"options":{"type":"object","description":"Settings describing the HTTP endpoint to call.","properties":{"url":{"type":["string","null"],"format":"uri","description":"HTTP(S) endpoint invoked when the step runs.","example":"https:\/\/cockpit.voxbi.com\/hooks\/call"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (send_to_email)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["send_to_email"],"description":"Step type. For this variant it emails a recording\/voicemail to recipients.","example":"send_to_email"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":3},"options":{"type":"object","description":"Settings describing the recording to attach and the recipients.","properties":{"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file (recording) to attach to the email.","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override; `null` (Auto) keeps the detected\/inherited language.","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"email":{"type":["string","null"],"format":"email","description":"Explicit recipient email address.","example":"support@example.com"},"email_user":{"type":["array","null"],"description":"Identifiers of users whose email addresses should receive the message.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440011"]},"email_to_called_user":{"type":"boolean","description":"When true, also emails the user who was originally called.","example":false}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (conference_room)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["conference_room"],"description":"Step type. For this variant it drops the caller into a conference room.","example":"conference_room"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the conference room extension.","properties":{"extension":{"type":["string","null"],"format":"uuid","description":"Identifier of the extension hosting the conference room.","example":"550e8400-e29b-41d4-a716-446655440030"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ivr_extension)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ivr_extension"],"description":"Step type. For this variant it plays a sound and waits for IVR-style key input.","example":"ivr_extension"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the sound file to play.","properties":{"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file to play before collecting input.","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override; `null` (Auto) keeps the detected\/inherited language.","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (multicast)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["multicast"],"description":"Step type. For this variant it pages a multicast (intercom) group.","example":"multicast"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the multicast group and access PIN.","properties":{"multicast_group":{"type":["string","null"],"description":"Name or identifier of the multicast paging group.","example":"paging-floor-1"},"multicast_pin":{"type":["string","null"],"description":"PIN required to join the multicast group.","example":"1234"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ai_assistant)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ai_assistant"],"description":"Step type. For this variant it hands the call off to a Smart IVR \/ AI agent.","example":"ai_assistant"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the AI provider and agent.","properties":{"ai_provider":{"type":"string","enum":["famulor"],"description":"AI provider backing the assistant.","example":"famulor"},"famulor_agent":{"type":["string","null"],"format":"uuid","description":"Identifier of the Famulor agent that handles the call.","example":"550e8400-e29b-41d4-a716-446655440070"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (hang_up)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["hang_up"],"description":"Step type. For this variant it terminates the call. This step has no configurable options.","example":"hang_up"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":4},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (start_recording)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["start_recording"],"description":"Step type. For this variant it begins call recording. This step has no configurable options.","example":"start_recording"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (answer)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["answer"],"description":"Step type. For this variant it explicitly answers the call. This step has no configurable options.","example":"answer"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}}],"discriminator":{"propertyName":"type"}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","call_flow_id":"550e8400-e29b-41d4-a716-446655440002","type":"ring_user","options":{"duration":20,"also_ring_dialed_extension":false,"also_ring_everyone_in_the_user_group":false,"dial_mobile_twinnings":false,"missed_calls":true,"music_on_hold":"550e8400-e29b-41d4-a716-446655440000","users":["550e8400-e29b-41d4-a716-446655440000"],"sip_devices":["550e8400-e29b-41d4-a716-446655440000"],"groups":["550e8400-e29b-41d4-a716-446655440000"],"tags":["550e8400-e29b-41d4-a716-446655440000"],"locations":["550e8400-e29b-41d4-a716-446655440000"],"languages":["550e8400-e29b-41d4-a716-446655440000"],"pools":["550e8400-e29b-41d4-a716-446655440000"],"statuses":["550e8400-e29b-41d4-a716-446655440000"],"pickup_lines":["550e8400-e29b-41d4-a716-446655440000"]}}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/calls\/new":{"post":{"tags":["Calls"],"summary":"Initiate a new call","operationId":"postCallNew","description":"Places an outbound call on behalf of the authenticated user.\n\n## Minimal request\n\n`destination` is the only required field. Everything else is optional:\n\n```json\n{ \"destination\": \"+12125550199\" }\n```\n\nWith nothing else supplied, the call is placed using the user's own configuration: their\ndefault caller identity and their default ringing targets as set up in the cockpit.\n\n## Choosing target devices\n\nSend `targets` when you want to override which of the user's endpoints should ring. Each\nflag is independent, so you can combine them (for example ring the desk phone and the\ntwinned mobile at the same time):\n\n```json\n{\n  \"destination\": \"+12125550199\",\n  \"targets\": {\n    \"sip_devices\": [],\n    \"webrtc\": false,\n    \"twinning\": true,\n    \"teams\": false\n  }\n}\n```\n\n- `sip_devices`: list of SIP device identifiers to ring. Omit or send `null` to let the PBX\n  pick the user's SIP devices.\n- `webrtc`: ring the browser softphone. Defaults to `false`.\n- `twinning`: ring the twinned (mobile) number. Defaults to `false`.\n- `teams`: ring the Microsoft Teams endpoint. Defaults to `false`.\n\nEvery boolean flag defaults to `false` when it is not passed, so a `targets` object is only\nuseful if at least one flag is `true` or `sip_devices` is populated.\n\nEnabling a target only has an effect if the matching configuration or integration exists for\nthe user: WebRTC requires a WebRTC-enabled account, `twinning` requires a twinning number,\nand `teams` requires the Teams integration. If the underlying feature is not configured, the\nPBX simply skips that target and rings whatever remains.\n\n## Caller identity\n\n`caller_identity` is optional. Pass the UUID of a caller identity available to the user to\npresent a specific outbound number. When omitted, the user's default caller identity is\nused.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"debugAmiTrace","in":"query","schema":{"type":"boolean"},"required":false,"description":"Enable AMI trace for debugging"},{"name":"autoAnswer","in":"query","schema":{"type":"boolean"},"required":false,"description":"Auto-answer the call"},{"name":"forceDialBack","in":"query","schema":{"type":"boolean"},"required":false,"description":"Force dial-back mode"},{"name":"anonymous","in":"query","schema":{"type":"boolean"},"required":false,"description":"Make the call anonymous"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["destination"],"properties":{"destination":{"type":"string","description":"The number or extension to dial. This is the only required field: a request\ncarrying nothing but `destination` places a valid call.\n","example":"+12125550199"},"caller_identity":{"type":"string","format":"uuid","description":"Optional. UUID of the caller identity (root number or identity) to present for\nthis call. Pass it only when this call should go out with a different identity\nthan usual. When omitted, the user's default caller identity is used.\n","example":"550e8400-e29b-41d4-a716-446655440000"},"targets":{"type":"object","description":"Optional. Overrides which of the user's endpoints ring. Omit the whole object to\nuse the user's configured targets. Every boolean defaults to `false` when not\npassed, so at least one flag should be `true` (or `sip_devices` populated) for a\n`targets` object to be meaningful. A flag only takes effect when the matching\nconfiguration or integration exists for the user; otherwise the PBX skips that\ntarget.\n","properties":{"sip_devices":{"type":["array","null"],"description":"SIP device identifiers to ring. Omit or send `null` to let the PBX resolve\nthe user's SIP devices.\n","items":{"type":"string"},"example":null},"webrtc":{"type":"boolean","description":"Ring the browser softphone. Defaults to `false`.","example":false},"twinning":{"type":"boolean","description":"Ring the twinned (mobile) number. Defaults to `false`.","example":false},"teams":{"type":"boolean","description":"Ring the Microsoft Teams endpoint. Defaults to `false`.","example":false}}}}},"examples":{"minimal":{"summary":"Simple call, destination only","description":"The smallest valid request. The user's default caller identity and configured targets are used.\n","value":{"destination":"+12125550199"}},"withTargets":{"summary":"Call ringing a specific set of targets","description":"Rings the twinned mobile instead of the default set. Flags left at `false` (and an empty `sip_devices`) are not rung.\n","value":{"destination":"+12125550199","targets":{"sip_devices":[],"webrtc":false,"twinning":true,"teams":false}}},"withCallerIdentity":{"summary":"Call presenting a specific caller identity","description":"Uses a different root number or identity for this call only, leaving the user's default untouched.\n","value":{"destination":"+12125550199","caller_identity":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"responses":{"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"},"data":{"type":"object"}}},"example":{"status":"success","message":"Call initiated successfully.","data":{"call_id":"abc123","destination":"+12125550199"}}}}},"400":{"description":"Bad Request","content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"error","message":"User PBX instance not found."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}},"500":{"description":"Internal Server Error","content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"error","message":"Failed to initiate call."}}}}}}},"\/ai-configuration":{"get":{"tags":["AiConfiguration"],"summary":"Get AI configuration (pbx)","operationId":"getAiConfiguration","description":"Returns the PBX's aggregated, read-only AI configuration: the account-wide\nglobal prompt and labels, the classification keyword tree, per-extension and\nper-group prompts, and the active AI profile and feature flags.\n\nRequires a PBX \"API key\" carrying the `ai-configuration` scope. The PBX is\nresolved from the token.\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Aggregated, read-only AI configuration for a PBX: the account-wide global\nprompt and labels, the classification keyword tree, per-extension and\nper-group prompts, and the active AI profile and feature flags.\n","required":["pbx_id","ai_features"],"properties":{"pbx_id":{"type":"string","format":"uuid","description":"PBX identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440000"},"ai_profile":{"type":["string","null"],"description":"Active AI plan for the PBX (null when the PBX is not on an AI plan)","enum":["unlimited","basic","premium",null],"example":"premium"},"ai_features":{"type":"object","description":"Enabled AI feature flags for the PBX","properties":{"summary":{"type":"boolean","example":true},"transcription":{"type":"boolean","example":true},"translations":{"type":"boolean","example":false},"keyword_mapping_to_call":{"type":"boolean","example":false},"tagging_calls":{"type":"boolean","example":false},"sentiment_analysis":{"type":"boolean","example":false}}},"global_prompt":{"type":["string","null"],"description":"Account-wide prompt every AI tool reads as ground truth","example":"You are the AI assistant for Example Corp. Be concise and polite."},"labels":{"type":"array","description":"Reusable classification labels, in display order","items":{"type":"string"},"example":["Sales","Support","Billing"]},"keywords":{"type":"array","description":"Hierarchical classification keywords. Each node carries an optional rule `prompt` and a `children` array of the same shape (recursively nested).\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","example":"Billing"},"prompt":{"type":["string","null"],"description":"The rule that tells the classifier when to apply this keyword","example":"Apply when the caller asks about invoices or payments."},"children":{"type":"array","description":"Nested child keywords, each of the same shape","items":{"type":"object"}}}}},"extension_prompts":{"type":"array","description":"Per-extension AI prompts","items":{"type":"object","properties":{"extension_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"extension":{"type":["string","null"],"description":"The extension number the prompt is attached to","example":"101"},"prompt":{"type":"string","example":"Greet callers as the reception desk and offer to take a message."}}}},"group_prompts":{"type":"array","description":"Per-group AI prompts","items":{"type":"object","properties":{"group_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"group":{"type":["string","null"],"description":"The group name the prompt is attached to","example":"Support"},"prompt":{"type":"string","example":"Prioritise urgent tickets and confirm the caller's contract number."}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The API key does not carry the `ai-configuration` scope."},"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}}}}},"\/contacts":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Contacts"],"summary":"List contact","operationId":"listContacts","description":"Returns a paginated list of contacts. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `id`, `name1`, `name2`, `email`, `company_name`, `department`, `job_title`, `is_private`, `is_blocked_globally`, `private_owner_id`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"},{"name":"include","description":"Comma-separated related resources to embed (dot-nested where\nshown). Allowed: `numbers`, `groups`, `blockedByUsers`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"numbers,groups"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Shared or personal address book entry. Phone numbers are held on the related\n`numbers` records. `handling_strategy` carries the polymorphic redirect target\nwhen inbound calls from this contact should be steered to a specific\ndestination.\n","required":["id","pbx_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Contact identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_name":{"type":["string","null"],"example":"Acme Corp"},"department":{"type":["string","null"],"example":"Engineering"},"job_title":{"type":["string","null"],"example":"Head of Product"},"name1":{"type":["string","null"],"description":"Primary name (first name, given name)","example":"Jane"},"name2":{"type":["string","null"],"description":"Secondary name (last name, surname)","example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"},"notes":{"type":["string","null"],"example":"Calls every Monday morning"},"vip":{"type":"boolean","description":"Whether the contact is flagged as VIP","example":false},"numbers":{"type":"array","description":"Phone numbers attached to this contact. Embed via `?include=numbers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"phone_number":{"type":"string","description":"The phone number (E.164 preferred)","example":"+12125550100"},"label":{"type":["string","null"],"description":"Optional label for the number","example":"Direct line"},"type":{"type":"string","description":"Kind of phone number","enum":["business","mobile","other","fax"],"example":"business"},"speed_dial":{"type":["string","null"],"description":"Optional speed-dial code for this number","example":"201"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"is_private":{"type":"boolean","description":"Private contacts are visible only to their `private_owner_id` user","example":false},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"Owner user when `is_private` is true","example":"550e8400-e29b-41d4-a716-446655440002"},"editable":{"type":"boolean","description":"Whether the **calling user** may edit this contact.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (which own all of their contacts).\n","example":true},"is_favorite":{"type":"boolean","description":"Whether this contact is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"groups":{"type":"array","description":"Groups this contact belongs to. Embed via `?include=groups`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"is_blocked_globally":{"type":"boolean","description":"Whether inbound calls from this contact are blocked tenant-wide","example":false},"blocked_by_users":{"type":"array","description":"Users who have personally blocked this contact, each as a user reference.\nEmbed via `?include=blockedByUsers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional polymorphic redirect target applied to inbound calls from this\ncontact. `type` discriminates which `*_id` field is meaningful.\n","properties":{"type":{"type":"string","enum":["call_flow","extension","user","sip_device"],"example":"call_flow"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["Contacts"],"summary":"Create a contact","operationId":"createContact","description":"Create an address-book contact. A contact is either private (owned by\n`private_owner_id`) or shared with a set of `groups` (the two are\nmutually exclusive). Phone numbers are sent in the nested\n`contactPhoneNumbers[]` array. `is_private` is derived from\n`private_owner_id` server-side and must not be sent.\n\nThe optional `handling_strategy` defines per-contact inbound routing.\n","security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name1"],"properties":{"name1":{"type":"string","minLength":3,"maxLength":64,"description":"Primary name (first \/ given name)"},"name2":{"type":["string","null"],"minLength":3,"maxLength":64,"description":"Secondary name (last \/ surname)"},"email":{"type":["string","null"],"format":"email","maxLength":50},"company_name":{"type":["string","null"],"minLength":2,"maxLength":64},"department":{"type":["string","null"],"minLength":2,"maxLength":64},"job_title":{"type":["string","null"],"minLength":3,"maxLength":32},"notes":{"type":["string","null"],"maxLength":500},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"When set, contact is private and visible only to this user. Mutually exclusive with `groups`."},"groups":{"type":"array","description":"Groups this contact is shared with. Mutually exclusive with `private_owner_id`.","items":{"type":"string","format":"uuid"}},"contactPhoneNumbers":{"type":"array","minItems":1,"description":"Phone numbers attached to the contact. When present, must contain at least one entry.","items":{"type":"object","required":["phone_number","type"],"properties":{"phone_number":{"type":"string","pattern":"^\\+?\\d*$","maxLength":24},"label":{"type":["string","null"],"maxLength":64},"type":{"type":"string","description":"Channel category (work, mobile, fax, etc.)"},"speed_dial":{"type":["string","null"],"description":"Speed-dial code (auto-prefixed with `*#`)"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional inbound-routing override for calls from this contact","additionalProperties":true}}},"example":{"name1":"Jane","name2":"Smith","email":"jane.smith@example.com","company_name":"Acme Corp","department":"Engineering","job_title":"Head of Product","notes":"Calls every Monday morning","groups":["550e8400-e29b-41d4-a716-446655440010"],"contactPhoneNumbers":[{"phone_number":"+12125550100","label":"Mobile","type":"mobile","speed_dial":"12"}]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Shared or personal address book entry. Phone numbers are held on the related\n`numbers` records. `handling_strategy` carries the polymorphic redirect target\nwhen inbound calls from this contact should be steered to a specific\ndestination.\n","required":["id","pbx_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Contact identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_name":{"type":["string","null"],"example":"Acme Corp"},"department":{"type":["string","null"],"example":"Engineering"},"job_title":{"type":["string","null"],"example":"Head of Product"},"name1":{"type":["string","null"],"description":"Primary name (first name, given name)","example":"Jane"},"name2":{"type":["string","null"],"description":"Secondary name (last name, surname)","example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"},"notes":{"type":["string","null"],"example":"Calls every Monday morning"},"vip":{"type":"boolean","description":"Whether the contact is flagged as VIP","example":false},"numbers":{"type":"array","description":"Phone numbers attached to this contact. Embed via `?include=numbers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"phone_number":{"type":"string","description":"The phone number (E.164 preferred)","example":"+12125550100"},"label":{"type":["string","null"],"description":"Optional label for the number","example":"Direct line"},"type":{"type":"string","description":"Kind of phone number","enum":["business","mobile","other","fax"],"example":"business"},"speed_dial":{"type":["string","null"],"description":"Optional speed-dial code for this number","example":"201"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"is_private":{"type":"boolean","description":"Private contacts are visible only to their `private_owner_id` user","example":false},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"Owner user when `is_private` is true","example":"550e8400-e29b-41d4-a716-446655440002"},"editable":{"type":"boolean","description":"Whether the **calling user** may edit this contact.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (which own all of their contacts).\n","example":true},"is_favorite":{"type":"boolean","description":"Whether this contact is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"groups":{"type":"array","description":"Groups this contact belongs to. Embed via `?include=groups`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"is_blocked_globally":{"type":"boolean","description":"Whether inbound calls from this contact are blocked tenant-wide","example":false},"blocked_by_users":{"type":"array","description":"Users who have personally blocked this contact, each as a user reference.\nEmbed via `?include=blockedByUsers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional polymorphic redirect target applied to inbound calls from this\ncontact. `type` discriminates which `*_id` field is meaningful.\n","properties":{"type":{"type":"string","enum":["call_flow","extension","user","sip_device"],"example":"call_flow"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/contacts\/{contact}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Contacts"],"summary":"Get a Contact","operationId":"getContact","description":"Returns the contact identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Shared or personal address book entry. Phone numbers are held on the related\n`numbers` records. `handling_strategy` carries the polymorphic redirect target\nwhen inbound calls from this contact should be steered to a specific\ndestination.\n","required":["id","pbx_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Contact identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_name":{"type":["string","null"],"example":"Acme Corp"},"department":{"type":["string","null"],"example":"Engineering"},"job_title":{"type":["string","null"],"example":"Head of Product"},"name1":{"type":["string","null"],"description":"Primary name (first name, given name)","example":"Jane"},"name2":{"type":["string","null"],"description":"Secondary name (last name, surname)","example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"},"notes":{"type":["string","null"],"example":"Calls every Monday morning"},"vip":{"type":"boolean","description":"Whether the contact is flagged as VIP","example":false},"numbers":{"type":"array","description":"Phone numbers attached to this contact. Embed via `?include=numbers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"phone_number":{"type":"string","description":"The phone number (E.164 preferred)","example":"+12125550100"},"label":{"type":["string","null"],"description":"Optional label for the number","example":"Direct line"},"type":{"type":"string","description":"Kind of phone number","enum":["business","mobile","other","fax"],"example":"business"},"speed_dial":{"type":["string","null"],"description":"Optional speed-dial code for this number","example":"201"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"is_private":{"type":"boolean","description":"Private contacts are visible only to their `private_owner_id` user","example":false},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"Owner user when `is_private` is true","example":"550e8400-e29b-41d4-a716-446655440002"},"editable":{"type":"boolean","description":"Whether the **calling user** may edit this contact.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (which own all of their contacts).\n","example":true},"is_favorite":{"type":"boolean","description":"Whether this contact is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"groups":{"type":"array","description":"Groups this contact belongs to. Embed via `?include=groups`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"is_blocked_globally":{"type":"boolean","description":"Whether inbound calls from this contact are blocked tenant-wide","example":false},"blocked_by_users":{"type":"array","description":"Users who have personally blocked this contact, each as a user reference.\nEmbed via `?include=blockedByUsers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional polymorphic redirect target applied to inbound calls from this\ncontact. `type` discriminates which `*_id` field is meaningful.\n","properties":{"type":{"type":"string","enum":["call_flow","extension","user","sip_device"],"example":"call_flow"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["Contacts"],"summary":"Update a contact","operationId":"updateContact","description":"Update an address-book contact. Same request shape as creation, with\n`name1` still required. `is_private` is derived from `private_owner_id`\nserver-side.\n","security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Contact identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name1"],"properties":{"name1":{"type":"string","minLength":3,"maxLength":64},"name2":{"type":["string","null"],"minLength":3,"maxLength":64},"email":{"type":["string","null"],"format":"email","maxLength":50},"company_name":{"type":["string","null"],"minLength":2,"maxLength":64},"department":{"type":["string","null"],"minLength":2,"maxLength":64},"job_title":{"type":["string","null"],"minLength":3,"maxLength":32},"notes":{"type":["string","null"],"maxLength":500},"private_owner_id":{"type":["string","null"],"format":"uuid"},"groups":{"type":"array","items":{"type":"string","format":"uuid"}},"contactPhoneNumbers":{"type":"array","items":{"type":"object","required":["phone_number","type"],"properties":{"phone_number":{"type":"string","pattern":"^\\+?\\d*$","maxLength":24},"label":{"type":["string","null"],"maxLength":64},"type":{"type":"string"},"speed_dial":{"type":["string","null"]}}}},"handling_strategy":{"type":["object","null"],"additionalProperties":true}}},"example":{"name1":"Jane","name2":"Smith-Doe","email":"jane.smithdoe@example.com","company_name":"Acme Corp","contactPhoneNumbers":[{"phone_number":"+12125550101","label":"Work","type":"work"}]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Shared or personal address book entry. Phone numbers are held on the related\n`numbers` records. `handling_strategy` carries the polymorphic redirect target\nwhen inbound calls from this contact should be steered to a specific\ndestination.\n","required":["id","pbx_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Contact identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_name":{"type":["string","null"],"example":"Acme Corp"},"department":{"type":["string","null"],"example":"Engineering"},"job_title":{"type":["string","null"],"example":"Head of Product"},"name1":{"type":["string","null"],"description":"Primary name (first name, given name)","example":"Jane"},"name2":{"type":["string","null"],"description":"Secondary name (last name, surname)","example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"},"notes":{"type":["string","null"],"example":"Calls every Monday morning"},"vip":{"type":"boolean","description":"Whether the contact is flagged as VIP","example":false},"numbers":{"type":"array","description":"Phone numbers attached to this contact. Embed via `?include=numbers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"phone_number":{"type":"string","description":"The phone number (E.164 preferred)","example":"+12125550100"},"label":{"type":["string","null"],"description":"Optional label for the number","example":"Direct line"},"type":{"type":"string","description":"Kind of phone number","enum":["business","mobile","other","fax"],"example":"business"},"speed_dial":{"type":["string","null"],"description":"Optional speed-dial code for this number","example":"201"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"is_private":{"type":"boolean","description":"Private contacts are visible only to their `private_owner_id` user","example":false},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"Owner user when `is_private` is true","example":"550e8400-e29b-41d4-a716-446655440002"},"editable":{"type":"boolean","description":"Whether the **calling user** may edit this contact.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (which own all of their contacts).\n","example":true},"is_favorite":{"type":"boolean","description":"Whether this contact is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"groups":{"type":"array","description":"Groups this contact belongs to. Embed via `?include=groups`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"is_blocked_globally":{"type":"boolean","description":"Whether inbound calls from this contact are blocked tenant-wide","example":false},"blocked_by_users":{"type":"array","description":"Users who have personally blocked this contact, each as a user reference.\nEmbed via `?include=blockedByUsers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional polymorphic redirect target applied to inbound calls from this\ncontact. `type` discriminates which `*_id` field is meaningful.\n","properties":{"type":{"type":"string","enum":["call_flow","extension","user","sip_device"],"example":"call_flow"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Contacts"],"summary":"Delete a contact","operationId":"deleteContact","description":"Soft-delete a contact. The contact is removed from list responses but can be restored by an administrator.","security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Contact identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/contacts\/{id}\/block":{"post":{"tags":["Contacts"],"summary":"Block a contact","operationId":"postContactBlock","description":"Triggers the action on the targeted contact block.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","description":"Contact ID","required":true,"schema":{"type":"integer","example":1}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"success","message":"Contact blocked."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/contacts\/{id}\/unblock":{"post":{"tags":["Contacts"],"summary":"Unblock a contact","operationId":"postContactUnblock","description":"Triggers the action on the targeted contact unblock.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","description":"Contact ID","required":true,"schema":{"type":"integer","example":1}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"success","message":"Contact unblocked."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/contacts\/favorite":{"post":{"tags":["Contacts"],"summary":"Toggle a contact as favorite","operationId":"postContactFavorite","description":"Creates a new contact favorite. Validation rules and required fields are defined in the\nrequest body schema below.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["contact_id"],"properties":{"contact_id":{"type":"integer","description":"ID of the contact to toggle as favorite","example":1}}},"example":{"contact_id":1}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"is_favorite":{"type":"boolean"}}},"example":{"status":"success","is_favorite":true}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/source\/{source}\/contacts":{"get":{"tags":["Contacts"],"summary":"Get contacts from a specific source","operationId":"getContactSourceContacts","description":"Returns the contact source contacts identified by the path parameter. Multi-tenant scoping\nis enforced: the caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"source","in":"path","description":"Source identifier","required":true,"schema":{"type":"string","example":"google"}},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Shared or personal address book entry. Phone numbers are held on the related\n`numbers` records. `handling_strategy` carries the polymorphic redirect target\nwhen inbound calls from this contact should be steered to a specific\ndestination.\n","required":["id","pbx_id"],"properties":{"id":{"type":"string","format":"uuid","description":"Contact identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_name":{"type":["string","null"],"example":"Acme Corp"},"department":{"type":["string","null"],"example":"Engineering"},"job_title":{"type":["string","null"],"example":"Head of Product"},"name1":{"type":["string","null"],"description":"Primary name (first name, given name)","example":"Jane"},"name2":{"type":["string","null"],"description":"Secondary name (last name, surname)","example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"},"notes":{"type":["string","null"],"example":"Calls every Monday morning"},"vip":{"type":"boolean","description":"Whether the contact is flagged as VIP","example":false},"numbers":{"type":"array","description":"Phone numbers attached to this contact. Embed via `?include=numbers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"phone_number":{"type":"string","description":"The phone number (E.164 preferred)","example":"+12125550100"},"label":{"type":["string","null"],"description":"Optional label for the number","example":"Direct line"},"type":{"type":"string","description":"Kind of phone number","enum":["business","mobile","other","fax"],"example":"business"},"speed_dial":{"type":["string","null"],"description":"Optional speed-dial code for this number","example":"201"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"is_private":{"type":"boolean","description":"Private contacts are visible only to their `private_owner_id` user","example":false},"private_owner_id":{"type":["string","null"],"format":"uuid","description":"Owner user when `is_private` is true","example":"550e8400-e29b-41d4-a716-446655440002"},"editable":{"type":"boolean","description":"Whether the **calling user** may edit this contact.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (which own all of their contacts).\n","example":true},"is_favorite":{"type":"boolean","description":"Whether this contact is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"groups":{"type":"array","description":"Groups this contact belongs to. Embed via `?include=groups`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"is_blocked_globally":{"type":"boolean","description":"Whether inbound calls from this contact are blocked tenant-wide","example":false},"blocked_by_users":{"type":"array","description":"Users who have personally blocked this contact, each as a user reference.\nEmbed via `?include=blockedByUsers`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}},"handling_strategy":{"type":["object","null"],"description":"Optional polymorphic redirect target applied to inbound calls from this\ncontact. `type` discriminates which `*_id` field is meaningful.\n","properties":{"type":{"type":"string","enum":["call_flow","extension","user","sip_device"],"example":"call_flow"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","company_name":"Acme Corp","department":"Engineering","job_title":"Head of Product","name1":"Jane","name2":"Smith","email":"jane.smith@example.com","notes":"Calls every Monday morning","is_private":false,"is_blocked_globally":false,"private_owner_id":"550e8400-e29b-41d4-a716-446655440002","handling_strategy":{"type":"call_flow","call_flow_id":"550e8400-e29b-41d4-a716-446655440000","extension_id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440000","sip_device_id":"550e8400-e29b-41d4-a716-446655440000"},"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/contacts\/imports":{"get":{"tags":["ContactImports"],"summary":"List your contact imports (user)","operationId":"listContactImports","description":"Returns a paginated list of the authenticated user's contact imports, newest\nfirst. This endpoint accepts a USER token only (not a PBX API key): a user\nonly ever sees their own imports.\n\nUse `filter[status]=incomplete` to narrow by lifecycle stage, and\n`?include=records,errors` to embed row-level detail.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","description":"Sort field. Prefix with `-` for descending. Allowed: `created_at`,\n`completed_at`, `status`. Defaults to `-created_at`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"-created_at"},{"name":"filter[status]","description":"Filter by exact lifecycle status (e.g. `incomplete`, `completed`).","in":"query","required":false,"schema":{"type":"string"},"example":"incomplete"},{"name":"include","description":"Comma-separated related detail to embed. Allowed: `records`, `errors`.","in":"query","required":false,"schema":{"type":"string"},"example":"records,errors"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}},"post":{"tags":["ContactImports"],"summary":"Upload a contact import file (user)","operationId":"createContactImport","description":"Uploads a CSV or Excel file and creates an import in the `incomplete` state.\nThe file is only stored at this step: no contacts are created yet. Next,\nconfigure parsing via the settings endpoint, map columns via the mapping\nendpoints, then confirm.\n\nAccepts a USER token only. The created import (and every contact it will\ncreate) is private to the authenticated user. Send the file as\n`multipart\/form-data` under the `file` key. Accepted types: CSV, XLS, XLSX.\n\nRate limited: at most one import may be created per minute per user. Only\nsuccessful creates count, so a rejected request (422) never blocks a valid\nretry. Configuring an existing import is not limited.\n\nNotification preferences may be set here or via the settings endpoint.\n","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The CSV or Excel file to import (max size configured server-side)."},"notify_owner_by_email":{"type":"boolean","description":"Email you once the import finishes (completed or failed).","default":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Public https URL. Import lifecycle events (pending, processing, completed, completed_with_errors, failed) are POSTed here as JSON, signed with an X-Voxbi-Signature (HMAC-SHA256) header. Typically used to drive live in-app notifications: point it at your backend, which relays each event to the signed-in user over your realtime channel (no polling). Any query params in the URL are echoed back on every delivery, so you can route the notification. Private, loopback and non-https URLs are rejected."}}}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created. The response is the import resource itself (unwrapped, not under\na `data` key). Fetch the detected columns next via the mapping-options\nendpoint.\n","content":{"application\/json":{"schema":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}},"429":{"description":"Too Many Requests. The rate limit for this action has been exceeded. Retry\nafter the window indicated by the Retry-After header.\n","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","example":60}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Too Many Attempts."}}}}}}},"\/contacts\/imports\/sample":{"get":{"tags":["ContactImports"],"summary":"Download a sample import file (user)","operationId":"getContactImportSample","description":"Downloads a headers-only sample CSV showing the contact fields the import\naccepts (the same file the Cockpit import wizard offers). Column headers are\nillustrative only: the import mapping is free-form, so you map your own\nfile's columns onto the target fields regardless of their headers.\n","security":[{"bearerAuth":[]}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. A CSV file download.","content":{"text\/csv":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/contacts\/imports\/{id}":{"get":{"tags":["ContactImports"],"summary":"Get one of your contact imports (user)","operationId":"getContactImport","description":"Returns a single import owned by the authenticated user. Use\n`?include=records,errors` to embed the imported contacts and any row-level\nfailures. Accepts a USER token only; another user's import returns 404.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}},{"name":"include","description":"Comma-separated related detail to embed. Allowed: `records`, `errors`.","in":"query","required":false,"schema":{"type":"string"},"example":"records,errors"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The import resource itself (unwrapped, not under a `data` key).","content":{"application\/json":{"schema":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"delete":{"tags":["ContactImports"],"summary":"Delete one of your contact imports (user)","operationId":"deleteContactImport","description":"Permanently deletes one of the authenticated user's imports, along with its\nrow-level records, errors, and the stored source file. An import in any\nstatus may be deleted; the contacts it already created are NOT removed.\nAccepts a USER token only; another user's import returns 404.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"No Content"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/contacts\/imports\/{id}\/settings":{"get":{"tags":["ContactImports"],"summary":"Get parsing settings for an import (user)","operationId":"getContactImportSettings","description":"Returns the parsing settings that apply to this import's file type, each with\nits type, default, and current value. The client renders exactly these; CSV\nimports expose `delimiter`, `enclosure`, and `input_encoding`, while Excel\nimports expose `sheet_index`. Only an `incomplete` import can be read here\n(otherwise 409).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","example":"input_encoding"},"type":{"type":"string","enum":["integer","boolean","string"],"example":"string"},"default":{"description":"Default value (type depends on `type`); may be null.","example":"UTF-8"},"current":{"description":"Currently stored value; may be null.","example":null},"allowed_values":{"type":"array","description":"Present only for settings with a fixed value set (e.g. `input_encoding`).","items":{"type":"string"},"example":["UTF-8","ISO-8859-1"]}}}},"example":[{"key":"header_row_position","type":"integer","default":1,"current":1},{"key":"skip_on_error","type":"boolean","default":true,"current":true},{"key":"delimiter","type":"string","default":null,"current":null}]}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict. The import is no longer in a state that allows this action (for\nexample, it has already been submitted for processing). Only an `incomplete`\nimport can be configured or confirmed.\n","headers":{"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Conflict","properties":{"message":{"type":"string"}}},"example":{"message":"This import has already been submitted."}}}}}},"put":{"tags":["ContactImports"],"summary":"Update parsing settings for an import (user)","operationId":"updateContactImportSettings","description":"Updates the parsing settings for an `incomplete` import. Send only the keys\nyou want to change. Only an `incomplete` import can be updated (otherwise\n409).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"header_row_position":{"type":["integer","null"],"minimum":1,"description":"1-based row that holds the column headers."},"sheet_index":{"type":["integer","null"],"minimum":0,"description":"0-based sheet to read (Excel files)."},"delimiter":{"type":["string","null"],"maxLength":5,"description":"CSV field delimiter."},"enclosure":{"type":["string","null"],"maxLength":5,"description":"CSV field enclosure character."},"input_encoding":{"type":["string","null"],"maxLength":50,"description":"Character encoding of the file; must be a supported encoding."},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import."},"notify_owner_by_email":{"type":"boolean","description":"Email you once the import finishes (completed or failed)."},"webhook_url":{"type":["string","null"],"format":"uri","description":"Public https URL. Import lifecycle events are POSTed here as JSON, signed with an X-Voxbi-Signature (HMAC-SHA256) header. Typically used to drive live in-app notifications: relay each event to the signed-in user over your realtime channel (no polling); query params in the URL are echoed back so you can route it. Private, loopback and non-https URLs are rejected. Send null to clear."}}},"example":{"header_row_position":1,"delimiter":",","input_encoding":"UTF-8","skip_on_error":true,"notify_owner_by_email":true,"webhook_url":"https:\/\/hooks.example.com\/imports"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The updated import resource (unwrapped). It carries the setting\nvalues just set (header_row_position, notify_owner_by_email, ...).\n","content":{"application\/json":{"schema":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict. The import is no longer in a state that allows this action (for\nexample, it has already been submitted for processing). Only an `incomplete`\nimport can be configured or confirmed.\n","headers":{"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Conflict","properties":{"message":{"type":"string"}}},"example":{"message":"This import has already been submitted."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/contacts\/imports\/{id}\/mapping-options":{"get":{"tags":["ContactImports"],"summary":"Get column mapping options for an import (user)","operationId":"getContactImportMappingOptions","description":"Returns everything the client needs to render the mapping step: the detected\nfile columns (each with a stable `id` used as `column` in the mapping\npayload) and the allow-listed target fields a column may be mapped to. Only\nthese target fields are accepted when saving a mapping: no other model\nattribute (e.g. `private_owner_id`, `pbx_id`, groups) can be targeted, and\nnothing is auto-mapped. Only an `incomplete` import can be read here\n(otherwise 409).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"file_columns":{"type":"array","description":"Detected columns from the uploaded file.","items":{"type":"object","properties":{"id":{"type":"integer","description":"Stable column id (used as `column` in the mapping payload).","example":0},"name":{"type":"string","description":"The column header text.","example":"First name"}}}},"target_fields":{"type":"array","description":"The only contact fields a column may be mapped to.","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"label":{"type":"string","example":"First name"},"type":{"type":"string","enum":["text","relationship"],"example":"text"},"multiple":{"type":"boolean","description":"Present (true) only on fields that accept several columns.","example":true},"subfields":{"type":"array","description":"Extra values a mapping to this field must carry (e.g. a phone `type`).","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"type":{"type":"string","example":"enum"},"options":{"type":"array","items":{"type":"string"},"example":["business","mobile","other","fax"]}}}}}}}}},"example":{"file_columns":[{"id":0,"name":"First name"},{"id":1,"name":"Last name"},{"id":2,"name":"Mobile"}],"target_fields":[{"field":"name1","label":"First name","type":"text"},{"field":"contactPhoneNumbers","label":"Phone numbers","type":"relationship","multiple":true,"subfields":[{"name":"type","type":"enum","options":["business","mobile","other","fax"]}]}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict. The import is no longer in a state that allows this action (for\nexample, it has already been submitted for processing). Only an `incomplete`\nimport can be configured or confirmed.\n","headers":{"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Conflict","properties":{"message":{"type":"string"}}},"example":{"message":"This import has already been submitted."}}}}}}},"\/contacts\/imports\/{id}\/mappings":{"put":{"tags":["ContactImports"],"summary":"Save the column mapping for an import (user)","operationId":"updateContactImportMappings","description":"Saves how the file's columns map onto contact fields. Each entry maps one\ncolumn (`column` = a `file_columns[].id` from mapping-options) onto one\n`field`. `field` must be one of the allow-listed target fields; any other\nvalue (including `private_owner_id`, `pbx_id`, `is_private`, or a groups\ncolumn) is rejected with 422, so a client cannot forge a mapping to assign\ncontacts to another user or tenant. A `contactPhoneNumbers` mapping must\ncarry a `type` sub-field. A single-value field may be mapped to at most one\ncolumn; only fields flagged `multiple: true` (currently\n`contactPhoneNumbers`) may take several columns, otherwise a duplicate\nmapping is rejected with 422. Only an `incomplete` import can be mapped\n(otherwise 409).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["mappings"],"properties":{"mappings":{"type":"array","minItems":1,"items":{"type":"object","required":["field","column"],"properties":{"field":{"type":"string","description":"An allow-listed target field (see mapping-options.target_fields).","example":"name1"},"column":{"type":"integer","minimum":0,"description":"A file column id from mapping-options.file_columns.","example":0},"subfields":{"type":"array","description":"Sub-field values required by the target field (e.g. a phone `type`).","items":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}}}},"example":{"mappings":[{"field":"name1","column":0},{"field":"name2","column":1},{"field":"contactPhoneNumbers","column":2,"subfields":[{"name":"type","value":"mobile"}]}]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The updated import resource (unwrapped).","content":{"application\/json":{"schema":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict. The import is no longer in a state that allows this action (for\nexample, it has already been submitted for processing). Only an `incomplete`\nimport can be configured or confirmed.\n","headers":{"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Conflict","properties":{"message":{"type":"string"}}},"example":{"message":"This import has already been submitted."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/contacts\/imports\/{id}\/confirm":{"post":{"tags":["ContactImports"],"summary":"Confirm and start an import (user)","operationId":"postContactImportConfirm","description":"Confirms an `incomplete` import and queues it for background processing. The\nimport must have a saved mapping (`can_confirm: true`) or a 422 is returned.\nOn success the import moves to `pending` and is processed asynchronously;\npoll the get-import endpoint for the final status and counts. Only an\n`incomplete` import can be confirmed (otherwise 409).\n\nImports created in the Cockpit admin are not drivable here, and an import\nstarted via this API cannot be completed from the Cockpit admin: the two\nflows are kept separate.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"Import identifier","schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The import resource (unwrapped), now `pending`.","content":{"application\/json":{"schema":{"type":"object","description":"An API-driven contact import. Every import is strictly owner-scoped: a user\nonly ever sees and drives their own imports, and every contact it creates is\nprivate to that user. The import moves through a small state machine:\n`incomplete` (being configured) -> `pending` (queued) -> `processing` ->\n`completed` \/ `completed_with_errors` \/ `failed`.\n\n`records` and `errors` are opt-in via `?include=records,errors` and are omitted\notherwise.\n","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid","description":"Import identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"status":{"type":"string","description":"Current stage of the import lifecycle","enum":["incomplete","pending","processing","completed","completed_with_errors","failed"],"example":"incomplete"},"file_type":{"type":["string","null"],"description":"Detected type of the uploaded file","enum":["csv","xls","xlsx",null],"example":"csv"},"records_count":{"type":"integer","description":"Number of contacts imported (populated once processed)","example":42},"errors_count":{"type":"integer","description":"Number of rows that failed to import","example":3},"can_confirm":{"type":"boolean","description":"True when the import is still incomplete and has a saved mapping, so it may be confirmed","example":true},"header_row_position":{"type":["integer","null"],"description":"1-based row holding the column headers.","example":1},"sheet_index":{"type":["integer","null"],"description":"0-based sheet to read (Excel files).","example":null},"delimiter":{"type":["string","null"],"description":"CSV field delimiter (auto-detected when null).","example":null},"enclosure":{"type":["string","null"],"description":"CSV field enclosure character.","example":"\""},"input_encoding":{"type":["string","null"],"description":"Character encoding of the file.","example":"UTF-8"},"skip_on_error":{"type":"boolean","description":"When true, invalid rows are skipped instead of failing the import.","example":true},"notify_owner_by_email":{"type":"boolean","description":"Whether the owner is emailed once the import finishes.","example":false},"webhook_url":{"type":["string","null"],"format":"uri","description":"Client webhook that receives lifecycle events.","example":null},"mappings":{"type":"array","description":"The saved column mapping, in the same shape it was submitted (empty until one is saved).","items":{"type":"object","properties":{"field":{"type":"string","example":"name1"},"column":{"type":"integer","example":0},"subfields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"type"},"value":{"type":"string","example":"mobile"}}}}}}},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-15T09:30:00Z","readOnly":true},"started_at":{"type":["string","null"],"format":"date-time","description":"When background processing began","example":"2026-01-15T09:31:00Z","readOnly":true},"completed_at":{"type":["string","null"],"format":"date-time","description":"When background processing finished","example":"2026-01-15T09:31:45Z","readOnly":true},"records":{"type":"array","description":"Imported contacts. Only present when requested via `?include=records`.","items":{"type":"object","properties":{"model_id":{"type":"string","format":"uuid","description":"Id of the created \/ updated contact","example":"550e8400-e29b-41d4-a716-446655440010"},"is_new":{"type":"boolean","description":"True when a new contact was created, false when an existing one was updated","example":true},"was_trashed":{"type":"boolean","description":"True when a soft-deleted contact was restored by the import","example":false}}}},"errors":{"type":"array","description":"Row-level failures. Only present when requested via `?include=errors`.","items":{"type":"object","properties":{"row":{"type":"integer","description":"1-based row number in the uploaded file","example":7},"attribute":{"type":["string","null"],"description":"The field that failed validation, when applicable","example":"email"},"messages":{"type":"array","items":{"type":"string"},"example":["The email must be a valid email address."]},"row_data":{"type":"object","additionalProperties":true,"description":"The offending row as read from the file","example":{"name1":"Jane","email":"not-an-email"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict. The import is no longer in a state that allows this action (for\nexample, it has already been submitted for processing). Only an `incomplete`\nimport can be configured or confirmed.\n","headers":{"Content-Type":{"schema":{"type":"string","example":"application\/json"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Conflict","properties":{"message":{"type":"string"}}},"example":{"message":"This import has already been submitted."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/extensions":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Extensions"],"summary":"List extension","operationId":"listExtensions","description":"Returns a paginated list of extensions. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `number`, `description`, `assigned_to_type`, `user.show_in_address_book`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"},{"name":"include","description":"Comma-separated related resources to embed (dot-nested where\nshown). Allowed: `famulorAgent`, `sipDevice`, `user`, `user.employee`, `user.groups`, `user.callerIdentities`, `user.callerIdentities.phoneNumber`, `user.sipDevices`, `user.twinnings`, `user.queues`, `user.queues.statuses`, `user.locations`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"user,user.groups"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/extensions\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Extensions"],"summary":"Get an Extension","operationId":"getExtension","description":"Returns the extension identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/favorite-extensions":{"get":{"tags":["Extensions"],"summary":"Get favorite extensions for the authenticated user","operationId":"getExtensionFavorites","description":"Returns a paginated list of extension favorites. Use the standard `search`, `sort`, `page`,\nand `perPage` query parameters; use `filter[key]=value` to narrow the result set.\nMulti-tenant scoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"pbx_id":{"type":"integer"},"extension":{"type":"string"},"user_id":{"type":["integer","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":1,"pbx_id":1,"extension":"101","user_id":2,"created_at":"2023-10-16T08:29:07.000000Z","updated_at":"2023-10-16T08:29:07.000000Z"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/groups":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Groups"],"summary":"List group","operationId":"listGroups","description":"Returns a paginated list of groups. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `description`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"},{"name":"include","description":"Comma-separated related resources to embed (dot-nested where\nshown). Allowed: `users`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"users"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","default_internal_call_flow_id":"550e8400-e29b-41d4-a716-446655440002","default_external_call_flow_id":"550e8400-e29b-41d4-a716-446655440003","default_caller_identity_id":"550e8400-e29b-41d4-a716-446655440004","extension_id_shown_outside_the_group":"550e8400-e29b-41d4-a716-446655440005","name":"Support team","description":"First-line support","allow_call_pickups":true,"allow_default_pbxes_outgoing_phone_numbers":false,"display_tab_to_everyone_inside_voxbi":false,"external_uid":"grp-support","created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["Groups"],"summary":"Create a group","operationId":"createGroup","description":"Create a group and optionally attach users, group permissions, and\npickup-lines \/ phone numbers. `pbx_id` is forced from the authenticated user.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["pbx_id","name"],"properties":{"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant). Must match the authenticated user's PBX."},"name":{"type":"string","minLength":3,"maxLength":64},"description":{"type":["string","null"],"minLength":3,"maxLength":255},"defaultInternalCallFlow":{"type":["string","null"],"format":"uuid"},"defaultExternalCallFlow":{"type":["string","null"],"format":"uuid"},"users":{"type":"array","description":"Member user identifiers","items":{"type":"string","format":"uuid"}},"pickupUsers":{"type":"array","description":"Users allowed to pick up calls in this group","items":{"type":"string","format":"uuid"}},"allowManageGroupContacts":{"type":"array","description":"Users allowed to manage this group's contacts","items":{"type":"string","format":"uuid"}},"allowAccessToGroupContacts":{"type":"array","description":"Users allowed to view this group's contacts","items":{"type":"string","format":"uuid"}},"phoneNumberAssignations":{"type":"array","description":"Phone numbers attached to the group","items":{"type":"string","format":"uuid"}},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX-default outbound numbers are usable from this group"},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is visible to all PBX users in Voxbi"},"callerIdentities":{"type":"array","description":"Outbound caller identities exposed to the group","items":{"type":"object","required":["phoneNumber"],"properties":{"phoneNumber":{"type":"string","format":"uuid"},"suffix":{"type":["string","null"],"pattern":"^\\d{0,5}\\*?$"},"label":{"type":["string","null"],"maxLength":255}}}}}},"example":{"pbx_id":"550e8400-e29b-41d4-a716-446655440001","name":"Customer Support","description":"First-line support team","users":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"],"allow_call_pickups":true,"allow_default_pbxes_outgoing_phone_numbers":false,"display_tab_to_everyone_inside_voxbi":false,"callerIdentities":[{"phoneNumber":"550e8400-e29b-41d4-a716-446655440020","suffix":"23","label":"Support line"}]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","name":"Customer Support","description":"First-line support team","allow_call_pickups":true,"allow_default_pbxes_outgoing_phone_numbers":false,"display_tab_to_everyone_inside_voxbi":false}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/groups\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Groups"],"summary":"Get a Group","operationId":"getGroup","description":"Returns the group identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/images\/{modelType}\/{modelId}":{"get":{"tags":["Images"],"summary":"List images for a model","operationId":"getImageList","description":"Returns the image list identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"modelType","in":"path","description":"The model type (e.g. user, contact)","required":true,"schema":{"type":"string","example":"user"}},{"name":"modelId","in":"path","description":"The model UUID","required":true,"schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Two-level keyed map of images, NOT a paginated list. Outer key is\nthe image type (from `ImageUploadType`); inner key is the usage\nidentifier (e.g. `avatar`, `wallpaper_main`).\n","properties":{"images":{"type":"object","description":"Images keyed by type then by usage","additionalProperties":{"type":"object","description":"Map of usage -> image metadata for this type","additionalProperties":{"type":"object","properties":{"id":{"type":"integer"},"filename":{"type":"string"},"mime_type":{"type":"string"},"size":{"type":"integer","description":"Size in bytes"},"width":{"type":"integer"},"height":{"type":"integer"},"url":{"type":"string","format":"uri"}}}}}}},"example":{"images":{"voxbi_desktop":{"logo_main":{"id":12,"filename":"voxbi-logo.png","mime_type":"image\/png","size":8421,"width":256,"height":64,"url":"https:\/\/cockpit.voxbi.com\/api\/v1\/images\/user\/550e8400-e29b-41d4-a716-446655440000\/logo_main?type=voxbi_desktop"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/images\/{modelType}\/{modelId}\/{usage}":{"get":{"tags":["Images"],"summary":"Get a specific image for a model by usage","operationId":"getImageGet","description":"Returns the image get identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"modelType","in":"path","description":"The model type (e.g. user, contact)","required":true,"schema":{"type":"string","example":"user"}},{"name":"modelId","in":"path","description":"The model UUID","required":true,"schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"usage","in":"path","description":"Image usage identifier (e.g. avatar, thumbnail)","required":true,"schema":{"type":"string","example":"avatar"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"integer"},"model_type":{"type":"string"},"model_id":{"type":"string","format":"uuid"},"usage":{"type":"string"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}},"example":{"data":{"id":1,"model_type":"user","model_id":"550e8400-e29b-41d4-a716-446655440000","usage":"avatar","url":"https:\/\/example.com\/images\/avatar.jpg","created_at":"2023-10-16T08:29:07.000000Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/ivrs":{"get":{"tags":["IVR"],"summary":"List ivr","operationId":"listIvrs","description":"Returns a paginated list of ivrs. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, pbx_id, name and comment.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Interactive Voice Response (IVR) menu. An IVR plays a sound file announcement\nand then routes the caller to a destination based on the digit they press. The\navailable digit-to-destination mappings are held on the related IVR steps,\nreturned inline in the `steps` array.\n","required":["id","pbx_id","name","announcement_id","steps"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR menu.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR. All IVRs are scoped to a single tenant.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":128,"description":"Human-readable label for the IVR menu, shown in the admin panel and used to identify the menu in call-flow configuration.","example":"Customer Support Menu"},"comment":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note describing the purpose or behaviour of this IVR. May be null.","example":"After-hours routing for the support line"},"announcement_id":{"type":"string","format":"uuid","description":"Identifier of the SoundFile announcement played to the caller when they enter this IVR menu. The referenced sound file is of type `announcement`.","example":"550e8400-e29b-41d4-a716-446655440002"},"announcement_language":{"type":["string","null"],"description":"Language override for this IVR's announcement. `null` (Auto) plays the\nlanguage variant detected\/inherited earlier in the call, falling back to the\nparent announcement. An ISO-639-1 code forces that specific variant.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"steps":{"type":"array","description":"Ordered collection of IVR steps belonging to this menu. Each step maps a\ncaller key press (or the default action) to a routing destination. The\narray is empty when no steps have been configured yet.\n","items":{"type":"object","description":"A single keypad option inside an IVR (Interactive Voice Response) menu. When a\ncaller reaches the parent IVR, the digit they press is matched against `option`\n(or the `default` step when no digit is pressed before the timeout) and the call\nis routed to the resource identified by the polymorphic `target_type` plus\n`target_id` pair. Legal routing targets are call flows and other IVRs, allowing\nnested menus.\n","required":["id","pbx_id","ivr_id","target_type","target_id","option","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR step.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR step.","example":"550e8400-e29b-41d4-a716-446655440001"},"ivr_id":{"type":"string","format":"uuid","description":"Identifier of the parent IVR menu this step belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"target_type":{"type":"string","description":"Polymorphic morph class of the routing target, stored as the fully\nqualified PHP class name. Together with `target_id` it identifies where the\ncall is routed when this option is selected. Valid targets are call flows\nand IVRs.\n","enum":["App\\Models\\CallFlow","App\\Models\\Ivr"],"example":"App\\Models\\CallFlow"},"target_id":{"type":"string","format":"uuid","description":"Identifier of the routing target resource. The kind of resource is given by\n`target_type` (a CallFlow or an Ivr).\n","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Optional human-readable label for this step, shown in the admin UI to\ndescribe where the option routes. Null when no label has been set.\n","example":"Sales department"},"option":{"type":"string","description":"The DTMF key that selects this step. The special value `default` is the\nfallback applied when the caller does not press any key before the IVR\ntimeout.\n","enum":["default","0","1","2","3","4","5","6","7","8","9","*","#"],"example":"1"},"language":{"type":["string","null"],"description":"Announcement language override applied from this step onward. `null` (Auto)\nmeans the language detected\/inherited earlier in the call is kept. ISO-639-1\ncode otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"voip_ivr_btn_id":{"type":["integer","null"],"format":"int32","description":"Legacy integer identifier used to correlate this step with the\ncorresponding button on the VoIP platform side. Null for steps that have no\nlegacy mapping.\n","example":42},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Null for active steps; set to the deletion time when\nthe step has been soft-deleted.\n","example":null,"readOnly":true}}}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","announcement_id":"550e8400-e29b-41d4-a716-446655440002","name":"Support IVR","comment":"Used for after-hours routing","default_action":"repeat","voip_ivr_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z","steps":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","ivr_id":"550e8400-e29b-41d4-a716-446655440002","name":"Sales department","option":"1","target_type":"App\\Models\\CallFlow","target_id":"550e8400-e29b-41d4-a716-446655440003","voip_ivr_btn_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}]}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["IVR"],"summary":"Create an IVR","operationId":"createIvr","description":"Create an IVR menu. `announcement` is the SoundFile of type `announcement`\nplayed when entering the menu; `musicOnHold` is an optional SoundFile of\ntype `music`. `default_action` controls what happens on caller timeout.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["pbx_id","name","announcement"],"properties":{"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant). Must match the authenticated user's PBX."},"name":{"type":"string","minLength":3,"maxLength":64},"comment":{"type":["string","null"],"maxLength":255},"announcement":{"type":"string","format":"uuid","description":"Sound file (type=announcement) played at the start of the menu"},"musicOnHold":{"type":["string","null"],"format":"uuid","description":"Sound file (type=music) played while caller is on hold"},"default_action":{"type":"string","enum":["hangup","repeat","default_step"],"description":"Behaviour on caller timeout"}}},"example":{"pbx_id":"550e8400-e29b-41d4-a716-446655440001","name":"Support IVR","comment":"Routes calls to sales or technical support","announcement":"550e8400-e29b-41d4-a716-446655440010","musicOnHold":"550e8400-e29b-41d4-a716-446655440011","default_action":"repeat"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Interactive Voice Response (IVR) menu. An IVR plays a sound file announcement\nand then routes the caller to a destination based on the digit they press. The\navailable digit-to-destination mappings are held on the related IVR steps,\nreturned inline in the `steps` array.\n","required":["id","pbx_id","name","announcement_id","steps"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR menu.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR. All IVRs are scoped to a single tenant.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":128,"description":"Human-readable label for the IVR menu, shown in the admin panel and used to identify the menu in call-flow configuration.","example":"Customer Support Menu"},"comment":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note describing the purpose or behaviour of this IVR. May be null.","example":"After-hours routing for the support line"},"announcement_id":{"type":"string","format":"uuid","description":"Identifier of the SoundFile announcement played to the caller when they enter this IVR menu. The referenced sound file is of type `announcement`.","example":"550e8400-e29b-41d4-a716-446655440002"},"announcement_language":{"type":["string","null"],"description":"Language override for this IVR's announcement. `null` (Auto) plays the\nlanguage variant detected\/inherited earlier in the call, falling back to the\nparent announcement. An ISO-639-1 code forces that specific variant.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"steps":{"type":"array","description":"Ordered collection of IVR steps belonging to this menu. Each step maps a\ncaller key press (or the default action) to a routing destination. The\narray is empty when no steps have been configured yet.\n","items":{"type":"object","description":"A single keypad option inside an IVR (Interactive Voice Response) menu. When a\ncaller reaches the parent IVR, the digit they press is matched against `option`\n(or the `default` step when no digit is pressed before the timeout) and the call\nis routed to the resource identified by the polymorphic `target_type` plus\n`target_id` pair. Legal routing targets are call flows and other IVRs, allowing\nnested menus.\n","required":["id","pbx_id","ivr_id","target_type","target_id","option","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR step.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR step.","example":"550e8400-e29b-41d4-a716-446655440001"},"ivr_id":{"type":"string","format":"uuid","description":"Identifier of the parent IVR menu this step belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"target_type":{"type":"string","description":"Polymorphic morph class of the routing target, stored as the fully\nqualified PHP class name. Together with `target_id` it identifies where the\ncall is routed when this option is selected. Valid targets are call flows\nand IVRs.\n","enum":["App\\Models\\CallFlow","App\\Models\\Ivr"],"example":"App\\Models\\CallFlow"},"target_id":{"type":"string","format":"uuid","description":"Identifier of the routing target resource. The kind of resource is given by\n`target_type` (a CallFlow or an Ivr).\n","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Optional human-readable label for this step, shown in the admin UI to\ndescribe where the option routes. Null when no label has been set.\n","example":"Sales department"},"option":{"type":"string","description":"The DTMF key that selects this step. The special value `default` is the\nfallback applied when the caller does not press any key before the IVR\ntimeout.\n","enum":["default","0","1","2","3","4","5","6","7","8","9","*","#"],"example":"1"},"language":{"type":["string","null"],"description":"Announcement language override applied from this step onward. `null` (Auto)\nmeans the language detected\/inherited earlier in the call is kept. ISO-639-1\ncode otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"voip_ivr_btn_id":{"type":["integer","null"],"format":"int32","description":"Legacy integer identifier used to correlate this step with the\ncorresponding button on the VoIP platform side. Null for steps that have no\nlegacy mapping.\n","example":42},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Null for active steps; set to the deletion time when\nthe step has been soft-deleted.\n","example":null,"readOnly":true}}}}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","announcement_id":"550e8400-e29b-41d4-a716-446655440010","name":"Support IVR","comment":"Routes calls to sales or technical support","default_action":"repeat"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/ivrs\/{id}":{"get":{"tags":["IVR"],"summary":"Get an IVR","operationId":"getIvr","description":"Returns the ivr identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Interactive Voice Response (IVR) menu. An IVR plays a sound file announcement\nand then routes the caller to a destination based on the digit they press. The\navailable digit-to-destination mappings are held on the related IVR steps,\nreturned inline in the `steps` array.\n","required":["id","pbx_id","name","announcement_id","steps"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR menu.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR. All IVRs are scoped to a single tenant.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":128,"description":"Human-readable label for the IVR menu, shown in the admin panel and used to identify the menu in call-flow configuration.","example":"Customer Support Menu"},"comment":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note describing the purpose or behaviour of this IVR. May be null.","example":"After-hours routing for the support line"},"announcement_id":{"type":"string","format":"uuid","description":"Identifier of the SoundFile announcement played to the caller when they enter this IVR menu. The referenced sound file is of type `announcement`.","example":"550e8400-e29b-41d4-a716-446655440002"},"announcement_language":{"type":["string","null"],"description":"Language override for this IVR's announcement. `null` (Auto) plays the\nlanguage variant detected\/inherited earlier in the call, falling back to the\nparent announcement. An ISO-639-1 code forces that specific variant.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"steps":{"type":"array","description":"Ordered collection of IVR steps belonging to this menu. Each step maps a\ncaller key press (or the default action) to a routing destination. The\narray is empty when no steps have been configured yet.\n","items":{"type":"object","description":"A single keypad option inside an IVR (Interactive Voice Response) menu. When a\ncaller reaches the parent IVR, the digit they press is matched against `option`\n(or the `default` step when no digit is pressed before the timeout) and the call\nis routed to the resource identified by the polymorphic `target_type` plus\n`target_id` pair. Legal routing targets are call flows and other IVRs, allowing\nnested menus.\n","required":["id","pbx_id","ivr_id","target_type","target_id","option","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR step.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR step.","example":"550e8400-e29b-41d4-a716-446655440001"},"ivr_id":{"type":"string","format":"uuid","description":"Identifier of the parent IVR menu this step belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"target_type":{"type":"string","description":"Polymorphic morph class of the routing target, stored as the fully\nqualified PHP class name. Together with `target_id` it identifies where the\ncall is routed when this option is selected. Valid targets are call flows\nand IVRs.\n","enum":["App\\Models\\CallFlow","App\\Models\\Ivr"],"example":"App\\Models\\CallFlow"},"target_id":{"type":"string","format":"uuid","description":"Identifier of the routing target resource. The kind of resource is given by\n`target_type` (a CallFlow or an Ivr).\n","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Optional human-readable label for this step, shown in the admin UI to\ndescribe where the option routes. Null when no label has been set.\n","example":"Sales department"},"option":{"type":"string","description":"The DTMF key that selects this step. The special value `default` is the\nfallback applied when the caller does not press any key before the IVR\ntimeout.\n","enum":["default","0","1","2","3","4","5","6","7","8","9","*","#"],"example":"1"},"language":{"type":["string","null"],"description":"Announcement language override applied from this step onward. `null` (Auto)\nmeans the language detected\/inherited earlier in the call is kept. ISO-639-1\ncode otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"voip_ivr_btn_id":{"type":["integer","null"],"format":"int32","description":"Legacy integer identifier used to correlate this step with the\ncorresponding button on the VoIP platform side. Null for steps that have no\nlegacy mapping.\n","example":42},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Null for active steps; set to the deletion time when\nthe step has been soft-deleted.\n","example":null,"readOnly":true}}}}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","announcement_id":"550e8400-e29b-41d4-a716-446655440002","name":"Support IVR","comment":"Used for after-hours routing","default_action":"repeat","voip_ivr_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z","steps":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","ivr_id":"550e8400-e29b-41d4-a716-446655440002","name":"Sales department","option":"1","target_type":"App\\Models\\CallFlow","target_id":"550e8400-e29b-41d4-a716-446655440003","voip_ivr_btn_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/ivr-steps":{"get":{"tags":["IVR Steps"],"summary":"List IVR step","operationId":"listIvrSteps","description":"Returns a paginated list of ivr steps. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, parent_id, ivr_id, sound_file_id, name, option, delay, action_type and action_value.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A single keypad option inside an IVR (Interactive Voice Response) menu. When a\ncaller reaches the parent IVR, the digit they press is matched against `option`\n(or the `default` step when no digit is pressed before the timeout) and the call\nis routed to the resource identified by the polymorphic `target_type` plus\n`target_id` pair. Legal routing targets are call flows and other IVRs, allowing\nnested menus.\n","required":["id","pbx_id","ivr_id","target_type","target_id","option","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR step.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR step.","example":"550e8400-e29b-41d4-a716-446655440001"},"ivr_id":{"type":"string","format":"uuid","description":"Identifier of the parent IVR menu this step belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"target_type":{"type":"string","description":"Polymorphic morph class of the routing target, stored as the fully\nqualified PHP class name. Together with `target_id` it identifies where the\ncall is routed when this option is selected. Valid targets are call flows\nand IVRs.\n","enum":["App\\Models\\CallFlow","App\\Models\\Ivr"],"example":"App\\Models\\CallFlow"},"target_id":{"type":"string","format":"uuid","description":"Identifier of the routing target resource. The kind of resource is given by\n`target_type` (a CallFlow or an Ivr).\n","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Optional human-readable label for this step, shown in the admin UI to\ndescribe where the option routes. Null when no label has been set.\n","example":"Sales department"},"option":{"type":"string","description":"The DTMF key that selects this step. The special value `default` is the\nfallback applied when the caller does not press any key before the IVR\ntimeout.\n","enum":["default","0","1","2","3","4","5","6","7","8","9","*","#"],"example":"1"},"language":{"type":["string","null"],"description":"Announcement language override applied from this step onward. `null` (Auto)\nmeans the language detected\/inherited earlier in the call is kept. ISO-639-1\ncode otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"voip_ivr_btn_id":{"type":["integer","null"],"format":"int32","description":"Legacy integer identifier used to correlate this step with the\ncorresponding button on the VoIP platform side. Null for steps that have no\nlegacy mapping.\n","example":42},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Null for active steps; set to the deletion time when\nthe step has been soft-deleted.\n","example":null,"readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","ivr_id":"550e8400-e29b-41d4-a716-446655440002","name":"Sales department","option":"1","target_type":"App\\Models\\CallFlow","target_id":"550e8400-e29b-41d4-a716-446655440003","voip_ivr_btn_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/ivr-steps\/{id}":{"get":{"tags":["IVR Steps"],"summary":"Get an IVR step","operationId":"getIvrStep","description":"Returns the ivr step identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"A single keypad option inside an IVR (Interactive Voice Response) menu. When a\ncaller reaches the parent IVR, the digit they press is matched against `option`\n(or the `default` step when no digit is pressed before the timeout) and the call\nis routed to the resource identified by the polymorphic `target_type` plus\n`target_id` pair. Legal routing targets are call flows and other IVRs, allowing\nnested menus.\n","required":["id","pbx_id","ivr_id","target_type","target_id","option","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the IVR step.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this IVR step.","example":"550e8400-e29b-41d4-a716-446655440001"},"ivr_id":{"type":"string","format":"uuid","description":"Identifier of the parent IVR menu this step belongs to.","example":"550e8400-e29b-41d4-a716-446655440002"},"target_type":{"type":"string","description":"Polymorphic morph class of the routing target, stored as the fully\nqualified PHP class name. Together with `target_id` it identifies where the\ncall is routed when this option is selected. Valid targets are call flows\nand IVRs.\n","enum":["App\\Models\\CallFlow","App\\Models\\Ivr"],"example":"App\\Models\\CallFlow"},"target_id":{"type":"string","format":"uuid","description":"Identifier of the routing target resource. The kind of resource is given by\n`target_type` (a CallFlow or an Ivr).\n","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"description":"Optional human-readable label for this step, shown in the admin UI to\ndescribe where the option routes. Null when no label has been set.\n","example":"Sales department"},"option":{"type":"string","description":"The DTMF key that selects this step. The special value `default` is the\nfallback applied when the caller does not press any key before the IVR\ntimeout.\n","enum":["default","0","1","2","3","4","5","6","7","8","9","*","#"],"example":"1"},"language":{"type":["string","null"],"description":"Announcement language override applied from this step onward. `null` (Auto)\nmeans the language detected\/inherited earlier in the call is kept. ISO-639-1\ncode otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"voip_ivr_btn_id":{"type":["integer","null"],"format":"int32","description":"Legacy integer identifier used to correlate this step with the\ncorresponding button on the VoIP platform side. Null for steps that have no\nlegacy mapping.\n","example":42},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the IVR step was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Null for active steps; set to the deletion time when\nthe step has been soft-deleted.\n","example":null,"readOnly":true}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","ivr_id":"550e8400-e29b-41d4-a716-446655440002","name":"Sales department","option":"1","target_type":"App\\Models\\CallFlow","target_id":"550e8400-e29b-41d4-a716-446655440003","voip_ivr_btn_id":1,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/languages":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Languages"],"summary":"List language","operationId":"listLanguages","description":"Returns a paginated list of languages. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `id`, `name`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Languages"],"summary":"Create a language","operationId":"createLanguage","description":"Enable a language for the PBX. `name` must be one of the supported locale\ndisplay names and unique within the PBX. `pbx_id` is forced from the\nauthenticated principal (a user's PBX, or the Pbx-owned API key itself) and\nis never read from the request body.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":64,"description":"Supported locale display name (must be unique within the PBX)"}}},"example":{"name":"English"}}}},"responses":{"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/languages\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Languages"],"summary":"Get a Language","operationId":"getLanguage","description":"Returns the language identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/locations":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Locations"],"summary":"List location","operationId":"listLocations","description":"Returns a paginated list of locations. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `description`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/locations\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Locations"],"summary":"Get a Location","operationId":"getLocation","description":"Returns the location identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/pbxes":{"get":{"tags":["Pbxes"],"summary":"List pbxe","operationId":"listPbxes","description":"Returns a paginated list of pbxes. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, default_carrier_id, fallback_carrier_id, profile_id, name, comment, reserved_extensions, emergency, automatic_firmware, default_call_pickups_for_new_extensions, phones_default_vlan_pc, phones_default_vlan_phone, phones_web_admin_password, lldp, show_users_first_name_first, allow_changing_record_calls, recordings_destination, oidc_enabled, oidc_allow_sign_up, oidc_email_domain, oidc_client_id, oidc_client_secret, oidc_discover_url, oidc_authorization_url, oidc_token_url, oidc_userinfo_url, oidc_logout_url, oidc_issuer and oidc_identity_fields_mapping.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"The tenant container. Every other resource in the API is scoped to a single\nPbx. A Pbx carries the telephony defaults, provisioning state, SSO settings,\nAI\/transcription options, capacity estimates, and branding for one customer\ninstance.\n\nSSO is configured through `sso_enabled` plus `sso_type` (`openid_connect` or\n`microsoft`) and the `sso_identity_fields_mapping` JSON; the actual OIDC\nendpoint details live on the related `IdentityProvider` records, not on this\nobject.\n\nHidden fields (`api_key`, `impersonation_token`, `user_provisioning_key`,\n`user_provisioning_ip_addresses`, `phones_web_admin_password`) are listed in\n`$hidden` on the model. They are accepted in write requests but are never\nreturned in any API response, so they are documented here as `writeOnly`.\n","required":["id","name","instance_name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the Pbx tenant.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"partner_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the partner (reseller) that manages this Pbx, or null if managed directly.","example":"550e8400-e29b-41d4-a716-446655440001"},"customer_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the customer record linked to this Pbx, or null if none is linked.","example":"550e8400-e29b-41d4-a716-446655440002"},"default_carrier_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default outbound SIP carrier used for external calls.","example":"550e8400-e29b-41d4-a716-446655440003"},"fallback_carrier_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the fallback SIP carrier used when the default carrier is unreachable.","example":"550e8400-e29b-41d4-a716-446655440004"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls that have no more specific routing.","example":"550e8400-e29b-41d4-a716-446655440005"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external calls that have no more specific routing.","example":"550e8400-e29b-41d4-a716-446655440006"},"no_ext_match_callflow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used when an inbound call matches no extension on the Pbx.","example":"550e8400-e29b-41d4-a716-446655440007"},"profile_id":{"type":["integer","null"],"format":"int64","description":"Legacy numeric profile identifier carried over from the previous platform.","example":42},"name":{"type":"string","maxLength":64,"description":"Human-readable display name of the Pbx tenant.","example":"Acme Corp"},"instance_name":{"type":"string","maxLength":50,"description":"Internal instance slug, unique across the platform and used to build deployment hostnames.","example":"pbx16dev"},"trunk_username":{"type":["string","null"],"maxLength":64,"description":"SIP trunk authentication username.","example":"trunk_acme"},"comment":{"type":["string","null"],"maxLength":255,"description":"Free-form internal comment about the Pbx.","example":"Migrated from legacy platform in March"},"reserved_extensions":{"type":"string","description":"Comma-separated list of extension numbers reserved from automatic\nassignment. Stored internally as JSON but always returned as a\ncomma-and-space joined string (empty string when none are reserved).\n","example":"112, 113, 911"},"emergency":{"type":"boolean","description":"Whether emergency-call handling is enabled for this Pbx.","example":false},"automatic_firmware":{"type":"boolean","description":"Whether managed device firmware updates are applied automatically.","example":true},"default_call_pickups_for_new_extensions":{"type":"boolean","description":"Whether newly created extensions get call-pickup enabled by default.","example":true},"allow_roaming":{"type":"boolean","description":"Whether users may hot-desk (roam) between SIP devices.","example":true},"phones_default_vlan_pc":{"type":["integer","null"],"format":"int32","description":"Default VLAN id assigned to the PC pass-through port on managed phones.","example":200},"phones_default_vlan_phone":{"type":["integer","null"],"format":"int32","description":"Default VLAN id assigned to the voice interface on managed phones.","example":100},"phones_web_admin_password":{"type":"string","writeOnly":true,"description":"Administrative password for the web interface of managed phones. Accepted\nin write requests but never returned (listed in the model `$hidden`).\n"},"lldp":{"type":"boolean","description":"Whether Link Layer Discovery Protocol is enabled on managed phones.","example":true},"show_users_first_name_first":{"type":"boolean","description":"Whether user display names are formatted with the first name before the last name.","example":true},"capitalize_users_last_name":{"type":"boolean","description":"Whether user last names are rendered in uppercase.","example":false},"allow_call_recording":{"type":"boolean","description":"Whether call recording is enabled tenant-wide.","example":false},"allow_changing_record_calls":{"type":"boolean","description":"Whether users may override the per-call recording behaviour.","example":false},"recordings_destination":{"type":"string","description":"Where call recordings are stored.","enum":["mixvoip","customer"],"example":"mixvoip"},"recording_start_at":{"type":"string","description":"At which point recording begins within a call.","enum":["on_start","on_bridge"],"example":"on_start"},"user_provisioning_key":{"type":"string","writeOnly":true,"description":"Secret key used to authenticate the user-provisioning API. Accepted in\nwrite requests but never returned (listed in the model `$hidden`).\n"},"user_provisioning_ip_addresses":{"type":"array","writeOnly":true,"items":{"type":"string"},"description":"Allow-list of IP addresses permitted to call the user-provisioning API.\nAccepted in write requests but never returned (listed in the model\n`$hidden`).\n"},"it_admin_notification_email":{"type":["string","null"],"format":"email","maxLength":255,"description":"Email address that receives IT administrator notifications for this Pbx.","example":"it@example.com"},"impersonation_token":{"type":"string","writeOnly":true,"description":"Token used by support staff to impersonate the tenant. Accepted in write\nrequests but never returned (listed in the model `$hidden`).\n"},"force_provisioning_sync":{"type":["string","null"],"format":"date-time","description":"Timestamp marking when a full provisioning re-sync was last forced. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_configuration":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last configuration push request. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_contact":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last contact-data push request. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_required":{"type":"boolean","description":"Whether the Pbx has pending configuration changes that still need to be pushed to the server.","example":false},"push_check_pending":{"type":"boolean","description":"Whether a configuration-push status check is currently in progress.","example":false},"push_check_requested_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the most recent push status check was requested.","example":"2024-03-01T08:29:07Z"},"push_required_count":{"type":"integer","format":"int32","description":"Number of configuration changes that require a push to the server.","example":0},"push_other_count":{"type":"integer","format":"int32","description":"Number of non-critical pending changes tracked alongside required pushes.","example":0},"server_push_date":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last successful configuration push applied on the server. Returned as a string.","example":"2024-03-01T08:29:07Z"},"contact_push_date":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last successful contact-data push applied on the server. Returned as a string.","example":"2024-03-01T08:29:07Z"},"last_config_update":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last configuration change made to the Pbx.","example":"2024-03-01T08:29:07Z"},"tenant_id":{"type":["string","null"],"description":"External tenant identifier (for example the Microsoft Entra tenant id).","example":"550e8400-e29b-41d4-a716-446655440099"},"sso_enabled":{"type":"boolean","description":"Whether single sign-on is enabled for this Pbx.","example":false},"sso_type":{"type":["string","null"],"description":"Single sign-on scheme in use, or null when SSO is disabled.","enum":["openid_connect","microsoft"],"example":"openid_connect"},"allow_sign_up_with_sso":{"type":"boolean","description":"Whether new users may self-register through SSO.","example":false},"force_sign_in_with_sso":{"type":"boolean","description":"Whether password sign-in is blocked and SSO is mandatory.","example":false},"max_incoming_channels":{"type":["integer","null"],"format":"int32","description":"Maximum number of simultaneous inbound channels permitted on this Pbx.","example":50},"max_incoming_channels_sound_file_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the SoundFile played to callers when the inbound channel limit is reached.","example":"550e8400-e29b-41d4-a716-446655440008"},"music_on_hold_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the SoundFile used as the default music on hold.","example":"550e8400-e29b-41d4-a716-446655440009"},"api_key":{"type":"string","writeOnly":true,"description":"Secret API key for the Pbx, used for provisioning authentication.\nAccepted in write requests but never returned (listed in the model\n`$hidden`).\n"},"sso_identity_fields_mapping":{"type":["object","null"],"description":"Mapping from internal user fields to the SSO claim names that supply\ntheir values. Returns null when SSO field mapping is not configured.\n","additionalProperties":true,"example":{"first_name":"given_name","last_name":"family_name","email":"email"}},"default_call_ring_duration":{"type":"integer","format":"int32","description":"Default ring duration in seconds applied across the Pbx.","example":30},"enable_soop_status":{"type":"boolean","description":"Whether the SOOP (status) presence feature is enabled for this Pbx.","example":true},"ai_profile":{"type":["string","null"],"description":"Selected AI capability profile that determines which AI features are\navailable and how they behave. Null when no AI profile is assigned.\n","enum":["basic","premium","unlimited"],"example":"premium"},"ai_engine_status":{"type":"boolean","description":"Whether the AI engine (transcription and summaries) is enabled for this Pbx.","example":false},"transcript_retention_days":{"type":["integer","null"],"format":"int32","description":"Number of days AI call transcripts are retained before deletion.","example":30},"last_ai_engine_status_activity_check":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last AI engine activity status check.","example":"2024-03-01T08:29:07Z"},"ring_tone":{"type":"string","description":"Country code selecting the ringtone profile used by managed phones.","enum":["lu","de","fr","be","nl","us","uk","pt","ch","at","it","es","bg","za"],"example":"lu"},"show_all_users_in_voxbi":{"type":"boolean","description":"Whether all tenant users are visible in the Voxbi softphone directory.","example":true},"split_internal_external_calls":{"type":"boolean","description":"Whether internal and external calls are presented and routed separately.","example":false},"call_block_logged_out_sip_devices":{"type":"boolean","description":"Whether outbound calls are blocked on SIP devices whose user is logged out.","example":true},"show_via_in_missed_call":{"type":"boolean","description":"Whether the \"via\" routing information is shown on missed-call notifications.","example":false},"enable_tempus_menu":{"type":"boolean","description":"Whether the Tempus time and attendance module menu is visible to this tenant.","example":true},"language":{"type":"string","description":"Default UI language for the Pbx.","enum":["en","de","fr"],"example":"en"},"estimated_users":{"type":"integer","format":"int32","description":"Estimated number of billable users on this Pbx.","example":25},"estimated_sip_devices":{"type":"integer","format":"int32","description":"Estimated number of billable SIP devices on this Pbx.","example":30},"multicast_sites_ip_addresses":{"type":["array","null"],"description":"IP addresses of the Mikrotik routers used for multicast paging, or null when none are configured.","items":{"type":"string"},"example":["10.10.0.1","10.10.0.2"]},"flags":{"type":["object","null"],"description":"Free-form feature-flag bag for tenant-specific opt-ins. Null when no flags are set.","additionalProperties":true,"example":{"beta_dashboard":true}},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was soft-deleted, or null if active.","example":null,"readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Corp","instance_name":"pbx16dev","partner_id":"550e8400-e29b-41d4-a716-446655440001","customer_id":"550e8400-e29b-41d4-a716-446655440002","profile_id":42,"default_carrier_id":"550e8400-e29b-41d4-a716-446655440003","fallback_carrier_id":"550e8400-e29b-41d4-a716-446655440004","default_internal_call_flow_id":"550e8400-e29b-41d4-a716-446655440005","default_external_call_flow_id":"550e8400-e29b-41d4-a716-446655440006","no_ext_match_callflow_id":"550e8400-e29b-41d4-a716-446655440007","default_call_flow_id":"550e8400-e29b-41d4-a716-446655440008","default_caller_id":"+12125550100","music_on_hold_id":"550e8400-e29b-41d4-a716-446655440009","max_incoming_channels":50,"max_incoming_channels_sound_file_id":"550e8400-e29b-41d4-a716-446655440000","trunk_username":"trunk_acme","reserved_extensions":"00, 11","emergency":true,"automatic_firmware":true,"default_call_pickups_for_new_extensions":true,"allow_roaming":true,"phones_default_vlan_pc":200,"phones_default_vlan_phone":100,"lldp":true,"show_users_first_name_first":true,"capitalize_users_last_name":false,"default_call_ring_duration":30,"ring_tone":"lu","language":"en","allow_call_recording":true,"allow_changing_record_calls":true,"recordings_destination":"mixvoip","recording_start_at":"on_bridge","transcript_retention_days":30,"sso_enabled":false,"sso_type":"openid_connect","allow_sign_up_with_sso":false,"force_sign_in_with_sso":false,"sso_identity_fields_mapping":{"first_name":"given_name","last_name":"family_name","email":"email"},"server_push_date":"2024-03-01T08:29:07Z","contact_push_date":"2024-03-01T08:29:07Z","push_required":false,"push_check_pending":false,"push_check_requested_at":"2024-03-01T08:29:07Z","push_required_count":0,"push_other_count":0,"last_config_update":"2024-03-01T08:29:07Z","it_admin_notification_email":"it@example.com","ai_engine_status":false,"last_ai_engine_status_activity_check":"2024-03-01T08:29:07Z","microsoft365_integration_enabled":false,"microsoft365_admin_consent_status":false,"enable_soop_status":false,"enable_tempus_menu":true,"show_all_users_in_voxbi":true,"show_via_in_missed_call":false,"split_internal_external_calls":false,"call_block_logged_out_sip_devices":false,"estimated_users":25,"estimated_sip_devices":30,"multicast_sites_ip_addresses":["10.10.0.1","10.10.0.2"],"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/pbxes\/{id}":{"get":{"tags":["Pbxes"],"summary":"Get a Pbx","operationId":"getPbx","description":"Returns the pbx identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"The tenant container. Every other resource in the API is scoped to a single\nPbx. A Pbx carries the telephony defaults, provisioning state, SSO settings,\nAI\/transcription options, capacity estimates, and branding for one customer\ninstance.\n\nSSO is configured through `sso_enabled` plus `sso_type` (`openid_connect` or\n`microsoft`) and the `sso_identity_fields_mapping` JSON; the actual OIDC\nendpoint details live on the related `IdentityProvider` records, not on this\nobject.\n\nHidden fields (`api_key`, `impersonation_token`, `user_provisioning_key`,\n`user_provisioning_ip_addresses`, `phones_web_admin_password`) are listed in\n`$hidden` on the model. They are accepted in write requests but are never\nreturned in any API response, so they are documented here as `writeOnly`.\n","required":["id","name","instance_name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the Pbx tenant.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"partner_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the partner (reseller) that manages this Pbx, or null if managed directly.","example":"550e8400-e29b-41d4-a716-446655440001"},"customer_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the customer record linked to this Pbx, or null if none is linked.","example":"550e8400-e29b-41d4-a716-446655440002"},"default_carrier_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default outbound SIP carrier used for external calls.","example":"550e8400-e29b-41d4-a716-446655440003"},"fallback_carrier_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the fallback SIP carrier used when the default carrier is unreachable.","example":"550e8400-e29b-41d4-a716-446655440004"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls that have no more specific routing.","example":"550e8400-e29b-41d4-a716-446655440005"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external calls that have no more specific routing.","example":"550e8400-e29b-41d4-a716-446655440006"},"no_ext_match_callflow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used when an inbound call matches no extension on the Pbx.","example":"550e8400-e29b-41d4-a716-446655440007"},"profile_id":{"type":["integer","null"],"format":"int64","description":"Legacy numeric profile identifier carried over from the previous platform.","example":42},"name":{"type":"string","maxLength":64,"description":"Human-readable display name of the Pbx tenant.","example":"Acme Corp"},"instance_name":{"type":"string","maxLength":50,"description":"Internal instance slug, unique across the platform and used to build deployment hostnames.","example":"pbx16dev"},"trunk_username":{"type":["string","null"],"maxLength":64,"description":"SIP trunk authentication username.","example":"trunk_acme"},"comment":{"type":["string","null"],"maxLength":255,"description":"Free-form internal comment about the Pbx.","example":"Migrated from legacy platform in March"},"reserved_extensions":{"type":"string","description":"Comma-separated list of extension numbers reserved from automatic\nassignment. Stored internally as JSON but always returned as a\ncomma-and-space joined string (empty string when none are reserved).\n","example":"112, 113, 911"},"emergency":{"type":"boolean","description":"Whether emergency-call handling is enabled for this Pbx.","example":false},"automatic_firmware":{"type":"boolean","description":"Whether managed device firmware updates are applied automatically.","example":true},"default_call_pickups_for_new_extensions":{"type":"boolean","description":"Whether newly created extensions get call-pickup enabled by default.","example":true},"allow_roaming":{"type":"boolean","description":"Whether users may hot-desk (roam) between SIP devices.","example":true},"phones_default_vlan_pc":{"type":["integer","null"],"format":"int32","description":"Default VLAN id assigned to the PC pass-through port on managed phones.","example":200},"phones_default_vlan_phone":{"type":["integer","null"],"format":"int32","description":"Default VLAN id assigned to the voice interface on managed phones.","example":100},"phones_web_admin_password":{"type":"string","writeOnly":true,"description":"Administrative password for the web interface of managed phones. Accepted\nin write requests but never returned (listed in the model `$hidden`).\n"},"lldp":{"type":"boolean","description":"Whether Link Layer Discovery Protocol is enabled on managed phones.","example":true},"show_users_first_name_first":{"type":"boolean","description":"Whether user display names are formatted with the first name before the last name.","example":true},"capitalize_users_last_name":{"type":"boolean","description":"Whether user last names are rendered in uppercase.","example":false},"allow_call_recording":{"type":"boolean","description":"Whether call recording is enabled tenant-wide.","example":false},"allow_changing_record_calls":{"type":"boolean","description":"Whether users may override the per-call recording behaviour.","example":false},"recordings_destination":{"type":"string","description":"Where call recordings are stored.","enum":["mixvoip","customer"],"example":"mixvoip"},"recording_start_at":{"type":"string","description":"At which point recording begins within a call.","enum":["on_start","on_bridge"],"example":"on_start"},"user_provisioning_key":{"type":"string","writeOnly":true,"description":"Secret key used to authenticate the user-provisioning API. Accepted in\nwrite requests but never returned (listed in the model `$hidden`).\n"},"user_provisioning_ip_addresses":{"type":"array","writeOnly":true,"items":{"type":"string"},"description":"Allow-list of IP addresses permitted to call the user-provisioning API.\nAccepted in write requests but never returned (listed in the model\n`$hidden`).\n"},"it_admin_notification_email":{"type":["string","null"],"format":"email","maxLength":255,"description":"Email address that receives IT administrator notifications for this Pbx.","example":"it@example.com"},"impersonation_token":{"type":"string","writeOnly":true,"description":"Token used by support staff to impersonate the tenant. Accepted in write\nrequests but never returned (listed in the model `$hidden`).\n"},"force_provisioning_sync":{"type":["string","null"],"format":"date-time","description":"Timestamp marking when a full provisioning re-sync was last forced. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_configuration":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last configuration push request. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_contact":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last contact-data push request. Returned as a string.","example":"2024-03-01T08:29:07Z"},"push_required":{"type":"boolean","description":"Whether the Pbx has pending configuration changes that still need to be pushed to the server.","example":false},"push_check_pending":{"type":"boolean","description":"Whether a configuration-push status check is currently in progress.","example":false},"push_check_requested_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the most recent push status check was requested.","example":"2024-03-01T08:29:07Z"},"push_required_count":{"type":"integer","format":"int32","description":"Number of configuration changes that require a push to the server.","example":0},"push_other_count":{"type":"integer","format":"int32","description":"Number of non-critical pending changes tracked alongside required pushes.","example":0},"server_push_date":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last successful configuration push applied on the server. Returned as a string.","example":"2024-03-01T08:29:07Z"},"contact_push_date":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last successful contact-data push applied on the server. Returned as a string.","example":"2024-03-01T08:29:07Z"},"last_config_update":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last configuration change made to the Pbx.","example":"2024-03-01T08:29:07Z"},"tenant_id":{"type":["string","null"],"description":"External tenant identifier (for example the Microsoft Entra tenant id).","example":"550e8400-e29b-41d4-a716-446655440099"},"sso_enabled":{"type":"boolean","description":"Whether single sign-on is enabled for this Pbx.","example":false},"sso_type":{"type":["string","null"],"description":"Single sign-on scheme in use, or null when SSO is disabled.","enum":["openid_connect","microsoft"],"example":"openid_connect"},"allow_sign_up_with_sso":{"type":"boolean","description":"Whether new users may self-register through SSO.","example":false},"force_sign_in_with_sso":{"type":"boolean","description":"Whether password sign-in is blocked and SSO is mandatory.","example":false},"max_incoming_channels":{"type":["integer","null"],"format":"int32","description":"Maximum number of simultaneous inbound channels permitted on this Pbx.","example":50},"max_incoming_channels_sound_file_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the SoundFile played to callers when the inbound channel limit is reached.","example":"550e8400-e29b-41d4-a716-446655440008"},"music_on_hold_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the SoundFile used as the default music on hold.","example":"550e8400-e29b-41d4-a716-446655440009"},"api_key":{"type":"string","writeOnly":true,"description":"Secret API key for the Pbx, used for provisioning authentication.\nAccepted in write requests but never returned (listed in the model\n`$hidden`).\n"},"sso_identity_fields_mapping":{"type":["object","null"],"description":"Mapping from internal user fields to the SSO claim names that supply\ntheir values. Returns null when SSO field mapping is not configured.\n","additionalProperties":true,"example":{"first_name":"given_name","last_name":"family_name","email":"email"}},"default_call_ring_duration":{"type":"integer","format":"int32","description":"Default ring duration in seconds applied across the Pbx.","example":30},"enable_soop_status":{"type":"boolean","description":"Whether the SOOP (status) presence feature is enabled for this Pbx.","example":true},"ai_profile":{"type":["string","null"],"description":"Selected AI capability profile that determines which AI features are\navailable and how they behave. Null when no AI profile is assigned.\n","enum":["basic","premium","unlimited"],"example":"premium"},"ai_engine_status":{"type":"boolean","description":"Whether the AI engine (transcription and summaries) is enabled for this Pbx.","example":false},"transcript_retention_days":{"type":["integer","null"],"format":"int32","description":"Number of days AI call transcripts are retained before deletion.","example":30},"last_ai_engine_status_activity_check":{"type":["string","null"],"format":"date-time","description":"Timestamp of the last AI engine activity status check.","example":"2024-03-01T08:29:07Z"},"ring_tone":{"type":"string","description":"Country code selecting the ringtone profile used by managed phones.","enum":["lu","de","fr","be","nl","us","uk","pt","ch","at","it","es","bg","za"],"example":"lu"},"show_all_users_in_voxbi":{"type":"boolean","description":"Whether all tenant users are visible in the Voxbi softphone directory.","example":true},"split_internal_external_calls":{"type":"boolean","description":"Whether internal and external calls are presented and routed separately.","example":false},"call_block_logged_out_sip_devices":{"type":"boolean","description":"Whether outbound calls are blocked on SIP devices whose user is logged out.","example":true},"show_via_in_missed_call":{"type":"boolean","description":"Whether the \"via\" routing information is shown on missed-call notifications.","example":false},"enable_tempus_menu":{"type":"boolean","description":"Whether the Tempus time and attendance module menu is visible to this tenant.","example":true},"language":{"type":"string","description":"Default UI language for the Pbx.","enum":["en","de","fr"],"example":"en"},"estimated_users":{"type":"integer","format":"int32","description":"Estimated number of billable users on this Pbx.","example":25},"estimated_sip_devices":{"type":"integer","format":"int32","description":"Estimated number of billable SIP devices on this Pbx.","example":30},"multicast_sites_ip_addresses":{"type":["array","null"],"description":"IP addresses of the Mikrotik routers used for multicast paging, or null when none are configured.","items":{"type":"string"},"example":["10.10.0.1","10.10.0.2"]},"flags":{"type":["object","null"],"description":"Free-form feature-flag bag for tenant-specific opt-ins. Null when no flags are set.","additionalProperties":true,"example":{"beta_dashboard":true}},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true},"deleted_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the Pbx was soft-deleted, or null if active.","example":null,"readOnly":true}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Corp","instance_name":"pbx16dev","partner_id":"550e8400-e29b-41d4-a716-446655440001","customer_id":"550e8400-e29b-41d4-a716-446655440002","profile_id":42,"default_carrier_id":"550e8400-e29b-41d4-a716-446655440003","fallback_carrier_id":"550e8400-e29b-41d4-a716-446655440004","default_internal_call_flow_id":"550e8400-e29b-41d4-a716-446655440005","default_external_call_flow_id":"550e8400-e29b-41d4-a716-446655440006","no_ext_match_callflow_id":"550e8400-e29b-41d4-a716-446655440007","default_call_flow_id":"550e8400-e29b-41d4-a716-446655440008","default_caller_id":"+12125550100","music_on_hold_id":"550e8400-e29b-41d4-a716-446655440009","max_incoming_channels":50,"max_incoming_channels_sound_file_id":"550e8400-e29b-41d4-a716-446655440000","trunk_username":"trunk_acme","reserved_extensions":"00, 11","emergency":true,"automatic_firmware":true,"default_call_pickups_for_new_extensions":true,"allow_roaming":true,"phones_default_vlan_pc":200,"phones_default_vlan_phone":100,"lldp":true,"show_users_first_name_first":true,"capitalize_users_last_name":false,"default_call_ring_duration":30,"ring_tone":"lu","language":"en","allow_call_recording":true,"allow_changing_record_calls":true,"recordings_destination":"mixvoip","recording_start_at":"on_bridge","transcript_retention_days":30,"sso_enabled":false,"sso_type":"openid_connect","allow_sign_up_with_sso":false,"force_sign_in_with_sso":false,"sso_identity_fields_mapping":{"first_name":"given_name","last_name":"family_name","email":"email"},"server_push_date":"2024-03-01T08:29:07Z","contact_push_date":"2024-03-01T08:29:07Z","push_required":false,"push_check_pending":false,"push_check_requested_at":"2024-03-01T08:29:07Z","push_required_count":0,"push_other_count":0,"last_config_update":"2024-03-01T08:29:07Z","it_admin_notification_email":"it@example.com","ai_engine_status":false,"last_ai_engine_status_activity_check":"2024-03-01T08:29:07Z","microsoft365_integration_enabled":false,"microsoft365_admin_consent_status":false,"enable_soop_status":false,"enable_tempus_menu":true,"show_all_users_in_voxbi":true,"show_via_in_missed_call":false,"split_internal_external_calls":false,"call_block_logged_out_sip_devices":false,"estimated_users":25,"estimated_sip_devices":30,"multicast_sites_ip_addresses":["10.10.0.1","10.10.0.2"],"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/numbers":{"get":{"tags":["Numbers"],"summary":"List phone numbers on the PBX","operationId":"listPbxNumbers","security":[{"IntegrationApiKey":[]}],"description":"List the PhoneNumbers attached to the caller's PBX (resolved from the bearer\ntoken). Each entry includes the currently-attached call flow (id + summary)\nwhen one is configured.\n\nThe list is **paginated** (`data` + `meta` + `links`) and supports filtering\nand sorting.\n","parameters":[{"in":"query","name":"filter[number]","required":false,"schema":{"type":"string"},"description":"Filter by phone number (substring match). A leading `+` is ignored, so\n`filter[number]=+4922` and `filter[number]=4922` both match.\n","example":"4922"},{"in":"query","name":"filter[name]","required":false,"schema":{"type":"string"},"description":"Filter by the number's name (substring match).","example":"Support"},{"in":"query","name":"sort","required":false,"schema":{"type":"string","enum":["number","-number","name","-name","created_at","-created_at"]},"description":"Sort field; prefix with `-` for descending. Allowed: `number`, `name`,\n`created_at`. Defaults to `number` ascending.\n","example":"-created_at"},{"in":"query","name":"page","required":false,"schema":{"type":"integer","minimum":1},"description":"Page number (1-based).","example":1},{"in":"query","name":"per_page","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"Items per page. Defaults to and is capped at 100 (the API page-length\nlimit); larger values are clamped to 100.\n","example":50}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"links":{"type":"object","description":"First\/last\/prev\/next page URLs."},"meta":{"type":"object","description":"Pagination metadata (current_page, per_page, total, last_page, ...)."}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","number":"+12125550100","name":"Customer Support","is_active":true,"call_flow_id":"550e8400-e29b-41d4-a716-446655440100","call_flow":{"id":"550e8400-e29b-41d4-a716-446655440100","name":"Business hours","enabled":true}}],"links":{"first":"https:\/\/cockpit.voxbi.com\/api\/v1\/numbers?page=1","last":"https:\/\/cockpit.voxbi.com\/api\/v1\/numbers?page=3","prev":null,"next":"https:\/\/cockpit.voxbi.com\/api\/v1\/numbers?page=2"},"meta":{"current_page":1,"per_page":50,"total":124,"last_page":3}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/numbers\/{id}\/call-flow":{"put":{"tags":["Numbers"],"summary":"Attach a call flow to a phone number","operationId":"updatePbxNumberCallFlow","security":[{"IntegrationApiKey":[]}],"description":"Set the handling strategy of a PhoneNumber to route incoming calls through\na specific call flow. Both the PhoneNumber and the CallFlow must belong to\nthe caller's PBX.\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"PhoneNumber UUID.","example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["call_flow_id"],"properties":{"call_flow_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"}}}}}},"responses":{"200":{"description":"Updated PhoneNumber with the new call flow attached.","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"PhoneNumber not found in the caller's PBX."},"422":{"description":"Validation error - call_flow_id missing, malformed, or doesn't belong\nto the caller's PBX.\n"}}}},"\/numbers\/orders\/check":{"post":{"tags":["Numbers"],"summary":"Check whether a phone number can be ordered at a given address","operationId":"checkPhoneNumberOrder","security":[{"IntegrationApiKey":[]}],"description":"Pre-flight check that validates an address with the upstream registry and\nreturns (a) the dial `prefix` for the resolved location, (b) the geocoder's\n`resolvedAddress`, and (c) the `kycRequirements` that must accompany the\nfuture order. Call this before `POST \/numbers\/orders`.\n\n### Comparing the address\n\nThe address is geocoded, so `resolvedAddress` may differ from what you sent\n(`address` echoes your input). Compare the two and, if they differ, confirm\nthe corrected values with the end user before placing the order - the order\nendpoint persists the geocoder-resolved values. Structured fields in\n`resolvedAddress` are nullable (the geocoder may fail to pin a component such\nas the street number); `formattedAddress` is always present.\n\n### Working with `kycRequirements`\n\n`kycRequirements` lists the KYC documents that must be supplied on\n`POST \/numbers\/orders`. Each **top-level entry** is either:\n\n  * an **object** - that exact document is required, or\n  * an **array of objects** - you must provide **any one** of the documents\n    listed inside (an \"OR group\").\n\nSo the example below requires **two** documents in total:\n\n  * either a `business_registration_certificate` **or** a `utility_bill`\n    (the OR group), **and**\n  * an `id_document` (the standalone entry).\n\nEach `documentType` is the code you reference when uploading on\n`POST \/numbers\/orders`: send file documents as a file part\n`kyc[<documentType>]` (e.g. `kyc[utility_bill]` carrying `bill.pdf`;\naccepted MIME types `application\/pdf`, `image\/jpeg`, `image\/png`), and\nidentifier-only documents as a form field\n`kyc[<documentType>]=<value>` (e.g. `kyc[business_registration_number]=BE-12345`).\n\nThe optional `notes` field carries country-specific context (the local name\nof the document, or a freshness constraint such as \"dated within 3 months\")\nand can be surfaced verbatim to the end user.\n","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["street","street_number","postal_code","city","country"],"properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"maxLength":16,"description":"Country-conditional. Required for some countries (e.g. Switzerland,\n`CH`, where it would be something like `43`) and must be omitted for\nothers - it is `null` for the `DE` example here. Send the same value\nyou will send to `POST \/numbers\/orders`.\n","example":null},"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO 3166-1 alpha-2 country code.","example":"DE"}}}}}},"responses":{"200":{"description":"Address resolved successfully; KYC requirements returned.","content":{"application\/json":{"schema":{"type":"object","properties":{"address":{"type":"object","description":"Echo of the address components you submitted.","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"country":{"type":"string","example":"DE"}}},"resolvedAddress":{"type":"object","description":"Address as resolved by the geocoder. Compare against `address`\nto detect corrections. Structured fields are nullable;\n`formattedAddress` is always present.\n","properties":{"street":{"type":["string","null"],"example":"Adenauerallee"},"streetNumber":{"type":["string","null"],"example":"1"},"postalCode":{"type":["string","null"],"example":"53113"},"city":{"type":["string","null"],"example":"Bonn"},"country":{"type":["string","null"],"example":"DE"},"formattedAddress":{"type":"string","description":"Human-readable resolved address. Always present.","example":"Adenauerallee 1, 53113 Bonn, Germany"}}},"prefix":{"type":"string","description":"Dial prefix for the resolved location in E.164 form with a\nleading `+` (country prefix plus area code where applicable).\n","example":"+49228"},"kycRequirements":{"type":"array","description":"KYC documents required on the future order. Each entry is\neither a single requirement object, or an array of objects\nmeaning \"provide any one of these\". See the endpoint\ndescription for how to upload each `documentType`.\n","items":{"oneOf":[{"type":"object","required":["documentType"],"properties":{"documentType":{"type":"string","description":"The KYC document type code. Reference it when uploading the document on\n`POST \/numbers\/orders` as `kyc[<documentType>]` (a file part for document\ntypes, or a form-field value for identifier-only types such as\n`business_registration_number`).\n","enum":["business_registration_certificate","utility_bill","id_document","business_registration_number"],"example":"utility_bill"},"notes":{"type":["string","null"],"description":"Country-specific context - the local name of the document or a freshness\nconstraint. Safe to surface verbatim to the end user.\n","example":"Dated within 3 months"}}},{"type":"array","items":{"type":"object","required":["documentType"],"properties":{"documentType":{"type":"string","description":"The KYC document type code. Reference it when uploading the document on\n`POST \/numbers\/orders` as `kyc[<documentType>]` (a file part for document\ntypes, or a form-field value for identifier-only types such as\n`business_registration_number`).\n","enum":["business_registration_certificate","utility_bill","id_document","business_registration_number"],"example":"utility_bill"},"notes":{"type":["string","null"],"description":"Country-specific context - the local name of the document or a freshness\nconstraint. Safe to surface verbatim to the end user.\n","example":"Dated within 3 months"}}}}]}}}},"example":{"address":{"street":"Adenauerallee","street_number":"1","postal_code":"53113","city":"Bonn","country":"DE"},"resolvedAddress":{"street":"Adenauerallee","streetNumber":"1","postalCode":"53113","city":"Bonn","country":"DE","formattedAddress":"Adenauerallee 1, 53113 Bonn, Germany"},"prefix":"+49228","kycRequirements":[[{"documentType":"business_registration_certificate","notes":"Handelsregister"},{"documentType":"utility_bill","notes":"Dated within 3 months"}],{"documentType":"id_document"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"The address failed validation - locally or upstream (e.g. it could not be\nresolved, or your account may not order numbers for that country). Same\n`{ message, errors }` shape as every other API validation 422, with\n`errors` mapping each rejected field to its messages. No order is created\nat this stage, so there is no `data`.\n\nWhen an upstream error has no field to attach to, `errors` is an empty\nobject `{}` and `message` carries the reason.\n","content":{"application\/json":{"schema":{"type":"object","required":["message","errors"],"additionalProperties":false,"properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"examples":{"validationError":{"summary":"Local validation - one or more fields invalid","value":{"message":"The street field is required. (and 1 more error)","errors":{"street":["The street field is required."],"street_number":["The street number field is required."]}}},"countryNotAllowed":{"summary":"Account not authorised to order in this country","value":{"message":"Phone numbers cannot be ordered for this country. Your account is not authorised to order numbers here - pick a different country or contact support.","errors":{"country":["Phone numbers cannot be ordered for this country. Your account is not authorised to order numbers here - pick a different country or contact support."]}}}}}}}}}},"\/numbers\/orders":{"post":{"tags":["Numbers"],"summary":"Place a phone number order","operationId":"createPhoneNumberOrder","security":[{"IntegrationApiKey":[]}],"description":"Submit a phone number order. Must be called as `multipart\/form-data` because\nKYC document files are part of the request. Call `POST \/numbers\/orders\/check`\nfirst to obtain the address-specific `kycRequirements`.\n\nYou may attach your own `order_id` (any short string, max 64 chars) - it\nwill be echoed back to you in the response, in `GET \/numbers\/orders\/{id}`,\nand in the asynchronous webhook payload below. If you omit it, the upstream\nprovider will generate one and we'll backfill it on your row.\n\nOrder fulfilment is asynchronous. This endpoint returns `201` as soon as the\norder is accepted upstream. The final outcome (success or rejection) will be\ndelivered to your `webhook` URL (if provided) and is queryable via\n`GET \/numbers\/orders\/{id}`.\n\n### Webhook payload\n\nWhen the order reaches its final state we POST to your `webhook` URL the\n**exact same body** as `GET \/numbers\/orders\/{id}` (the schema below). Read\nthe `status` field to tell success from rejection:\n\n  * `status: \"success\"` - `numbers` and `phone_numbers` are populated.\n  * `status: \"error\"` - `error_message` carries the rejection reason.\n","requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"type":"object","required":["customer_name","street","street_number","postal_code","city","country","quantity"],"properties":{"customer_name":{"type":"string","maxLength":255,"description":"Legal name of the customer the numbers are ordered for. Required;\nforwarded to the carrier, which records and may validate it.\n","example":"ACME GmbH"},"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"maxLength":16,"description":"Country-conditional. Required for some countries (e.g. Switzerland,\n`CH`, where it would be something like `43`) and rejected (422) for\nothers - it is `null` for the `DE` example here. Use the same value\nyou sent to `POST \/numbers\/orders\/check`.\n","example":null},"country":{"type":"string","example":"DE"},"quantity":{"type":"integer","minimum":1,"example":1},"webhook":{"type":["string","null"],"format":"uri","description":"Optional URL we POST to once the order is fulfilled. The order is\naccepted asynchronously (this endpoint returns `201` with status\n`requested`), so the assigned numbers - or a rejection - are\ndelivered here later, not in this response. See \"Webhook payloads\"\nabove for the exact body. The same outcome can also be fetched from\n`GET \/numbers\/orders\/{id}`.\n","maxLength":500,"example":"https:\/\/your-app.example\/hooks\/number-order"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Optional customer reference (any short string, max 64 chars).\nEchoed back in the response, in `GET \/numbers\/orders\/{id}`, and\nat the top level of the asynchronous webhook payload as\n`order_id` (the webhook body is the same order object). If\nomitted, the upstream provider generates one and we backfill it\non your row.\n","example":"po-2026-00042"},"kyc":{"type":"object","additionalProperties":true,"description":"KYC documents, one entry per `documentType` returned by\n`POST \/numbers\/orders\/check` for the country. Send file documents\nas a file part `kyc[<documentType>]` and identifier-only documents\nas a form field `kyc[<documentType>]=<value>`. Accepted file MIME\ntypes: `application\/pdf`, `image\/jpeg`, `image\/png`. Example shape:\n\n  * `kyc[utility_bill]` - file part carrying `bill.pdf`\n  * `kyc[id_document]` - file part carrying `passport.jpg`\n  * `kyc[business_registration_number]=BE-12345` - form field\n\nFor an OR group returned by the check endpoint (an array of types),\nprovide any one of the listed `documentType`s.\n"}}}}}},"responses":{"201":{"description":"Order accepted upstream and persisted on our side.","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Internal order id assigned by us. Use this with `GET \/numbers\/orders\/{id}`\nto fetch the latest state. NOT the value echoed in the asynchronous\nwebhook payload - that one is `order_id` (your own reference).\n","example":"550e8400-e29b-41d4-a716-446655440000"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Your customer reference, supplied via the `order_id` field in\n`POST \/numbers\/orders` (or `POST \/numbers\/orders\/{id}`). Echoed back here,\nin `GET \/numbers\/orders\/{id}`, and at the top level of the asynchronous\nwebhook payload (which is this same object) as `order_id`.\n","example":"po-2026-00042"},"customer_name":{"type":"string","description":"Legal name of the customer the numbers were ordered for, as supplied on\ncreate (and editable on retry).\n","example":"ACME GmbH"},"status":{"type":"string","enum":["created","requested","submission_failed","processing","success","error","processing_failed"],"description":"Lifecycle state of this order.\n * `requested`: sent upstream, awaiting fulfilment.\n * `submission_failed`: rejected during synchronous submission; editable + retryable.\n * `processing`: async success callback received; provisioning in progress.\n * `success`: provisioning complete; `numbers` is populated.\n * `error`: async rejection; terminal.\n * `processing_failed`: internal processing exhausted retries; admin-only retry.\n","example":"requested"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"description":"Country-conditional (e.g. set for CH); null otherwise.","example":null},"country":{"type":"string","example":"DE"}}},"formatted_address":{"type":["string","null"],"description":"Single-line, comma-separated address derived from the persisted\ncomponents (street + number, postal code + city, country). Empty\ncomponents are dropped.\n","example":"Adenauerallee 1, 53113 Bonn, DE"},"quantity":{"type":"integer","example":1},"prefix":{"type":["string","null"],"description":"Dial prefix in E.164 (country + area code if applicable).","example":"+49228"},"numbers":{"type":"array","description":"E.164-formatted numbers assigned to this order. Empty (`[]`) until the\norder reaches `success` - they are never returned synchronously by\n`POST \/numbers\/orders` (which only ever returns `requested`); they arrive\nlater via the webhook and then appear here on `GET \/numbers\/orders\/{id}`.\n","items":{"type":"string"},"example":["+4922812345678"]},"phone_numbers":{"type":"array","description":"The assigned numbers, in the same shape as `GET \/numbers`\n(id, number, name, is_active, call_flow), so you can read each number's id\nand current call flow and act on it directly (e.g. `PUT \/numbers\/{id}\/call-flow`).\nPopulated once the order reaches `success`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"error_message":{"type":["string","null"],"description":"Short error reason when status is `error` or `submission_failed`."},"webhook_url":{"type":["string","null"],"description":"The webhook URL we will POST the final outcome to."},"webhook_status":{"type":"string","enum":["not_required","pending","retrying","delivered","failed","cancelled"]},"webhook_next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","order_id":"po-2026-00042","customer_name":"ACME GmbH","status":"requested","address":{"street":"Adenauerallee","street_number":"1","postal_code":"53113","city":"Bonn","area_code":null,"country":"DE"},"formatted_address":"Adenauerallee 1, 53113 Bonn, DE","quantity":1,"prefix":"+49228","numbers":[],"phone_numbers":[],"error_message":null,"webhook_url":"https:\/\/your-app.example\/hooks\/number-order","webhook_status":"pending","webhook_next_retry_at":null,"created_at":"2026-05-12T10:36:47+00:00","updated_at":"2026-05-12T10:36:47+00:00"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Validation failed. `errors` maps each rejected field to its messages.\n\nIf the order reached the carrier and was rejected there, it is persisted\nas a retryable `submission_failed` order and returned in `data` (the full\norder, same shape as `GET \/numbers\/orders\/{id}`); use `data.id` to edit +\nretry it via `POST \/numbers\/orders\/{id}`. When `data` is absent, no order\nwas created.\n","content":{"application\/json":{"schema":{"type":"object","required":["message","errors"],"additionalProperties":false,"properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"data":{"description":"Present only for a carrier rejection (a retryable order was\npersisted). The full order - same shape as\n`GET \/numbers\/orders\/{id}` - whose `id` you pass to\n`POST \/numbers\/orders\/{id}` to edit + retry. Absent for local\nvalidation errors.\n","allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Internal order id assigned by us. Use this with `GET \/numbers\/orders\/{id}`\nto fetch the latest state. NOT the value echoed in the asynchronous\nwebhook payload - that one is `order_id` (your own reference).\n","example":"550e8400-e29b-41d4-a716-446655440000"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Your customer reference, supplied via the `order_id` field in\n`POST \/numbers\/orders` (or `POST \/numbers\/orders\/{id}`). Echoed back here,\nin `GET \/numbers\/orders\/{id}`, and at the top level of the asynchronous\nwebhook payload (which is this same object) as `order_id`.\n","example":"po-2026-00042"},"customer_name":{"type":"string","description":"Legal name of the customer the numbers were ordered for, as supplied on\ncreate (and editable on retry).\n","example":"ACME GmbH"},"status":{"type":"string","enum":["created","requested","submission_failed","processing","success","error","processing_failed"],"description":"Lifecycle state of this order.\n * `requested`: sent upstream, awaiting fulfilment.\n * `submission_failed`: rejected during synchronous submission; editable + retryable.\n * `processing`: async success callback received; provisioning in progress.\n * `success`: provisioning complete; `numbers` is populated.\n * `error`: async rejection; terminal.\n * `processing_failed`: internal processing exhausted retries; admin-only retry.\n","example":"requested"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"description":"Country-conditional (e.g. set for CH); null otherwise.","example":null},"country":{"type":"string","example":"DE"}}},"formatted_address":{"type":["string","null"],"description":"Single-line, comma-separated address derived from the persisted\ncomponents (street + number, postal code + city, country). Empty\ncomponents are dropped.\n","example":"Adenauerallee 1, 53113 Bonn, DE"},"quantity":{"type":"integer","example":1},"prefix":{"type":["string","null"],"description":"Dial prefix in E.164 (country + area code if applicable).","example":"+49228"},"numbers":{"type":"array","description":"E.164-formatted numbers assigned to this order. Empty (`[]`) until the\norder reaches `success` - they are never returned synchronously by\n`POST \/numbers\/orders` (which only ever returns `requested`); they arrive\nlater via the webhook and then appear here on `GET \/numbers\/orders\/{id}`.\n","items":{"type":"string"},"example":["+4922812345678"]},"phone_numbers":{"type":"array","description":"The assigned numbers, in the same shape as `GET \/numbers`\n(id, number, name, is_active, call_flow), so you can read each number's id\nand current call flow and act on it directly (e.g. `PUT \/numbers\/{id}\/call-flow`).\nPopulated once the order reaches `success`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"error_message":{"type":["string","null"],"description":"Short error reason when status is `error` or `submission_failed`."},"webhook_url":{"type":["string","null"],"description":"The webhook URL we will POST the final outcome to."},"webhook_status":{"type":"string","enum":["not_required","pending","retrying","delivered","failed","cancelled"]},"webhook_next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}]}}},"examples":{"validationError":{"summary":"Local validation - one or more fields invalid","value":{"message":"The customer name field is required. (and 9 more errors)","errors":{"customer_name":["The customer name field is required."],"street":["The street field is required."],"street_number":["The street number field is required."],"postal_code":["The postal code field is required."],"city":["The city field is required."],"country":["The country field is required."],"area_code":["The area code field is required."],"quantity":["The quantity field must be at least 1."],"webhook":["The webhook field must be a valid URL."],"order_id":["The order id field must not be greater than 64 characters."]}}},"carrierRejection":{"summary":"Carrier rejected the order (mapped to your fields)","value":{"message":"This value is too short. It should have 3 characters or more. (and 1 more error)","errors":{"customer_name":["This value is too short. It should have 3 characters or more."],"city":["The city does not match the provided postal code."]},"data":{"id":"550e8400-e29b-41d4-a716-446655440000","order_id":"po-2026-00042","customer_name":"ACME GmbH","status":"submission_failed","address":{"street":"Adenauerallee","street_number":"1","postal_code":"53113","city":"Bonn","area_code":null,"country":"DE"},"formatted_address":"Adenauerallee 1, 53113 Bonn, DE","quantity":1,"prefix":null,"numbers":[],"phone_numbers":[],"error_message":"Nexus rejected the request with status 422","webhook_url":"https:\/\/your-app.example\/hooks\/number-order","webhook_status":"not_required","webhook_next_retry_at":null,"created_at":"2026-05-12T10:36:47+00:00","updated_at":"2026-05-12T10:36:47+00:00"}}}}}}}}}},"\/numbers\/orders\/{id}":{"get":{"tags":["Numbers"],"summary":"Get a phone number order","operationId":"getPhoneNumberOrder","security":[{"IntegrationApiKey":[]}],"description":"Retrieve the current state of a phone number order. The order outcome\n(assigned numbers on success, or the rejection reason) can be fetched here\nif you cannot accept the webhook callback, and it also lets you inspect a\npast order's audit trail.\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order UUID returned by `POST \/numbers\/orders`.","example":"550e8400-e29b-41d4-a716-446655440000"}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Internal order id assigned by us. Use this with `GET \/numbers\/orders\/{id}`\nto fetch the latest state. NOT the value echoed in the asynchronous\nwebhook payload - that one is `order_id` (your own reference).\n","example":"550e8400-e29b-41d4-a716-446655440000"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Your customer reference, supplied via the `order_id` field in\n`POST \/numbers\/orders` (or `POST \/numbers\/orders\/{id}`). Echoed back here,\nin `GET \/numbers\/orders\/{id}`, and at the top level of the asynchronous\nwebhook payload (which is this same object) as `order_id`.\n","example":"po-2026-00042"},"customer_name":{"type":"string","description":"Legal name of the customer the numbers were ordered for, as supplied on\ncreate (and editable on retry).\n","example":"ACME GmbH"},"status":{"type":"string","enum":["created","requested","submission_failed","processing","success","error","processing_failed"],"description":"Lifecycle state of this order.\n * `requested`: sent upstream, awaiting fulfilment.\n * `submission_failed`: rejected during synchronous submission; editable + retryable.\n * `processing`: async success callback received; provisioning in progress.\n * `success`: provisioning complete; `numbers` is populated.\n * `error`: async rejection; terminal.\n * `processing_failed`: internal processing exhausted retries; admin-only retry.\n","example":"requested"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"description":"Country-conditional (e.g. set for CH); null otherwise.","example":null},"country":{"type":"string","example":"DE"}}},"formatted_address":{"type":["string","null"],"description":"Single-line, comma-separated address derived from the persisted\ncomponents (street + number, postal code + city, country). Empty\ncomponents are dropped.\n","example":"Adenauerallee 1, 53113 Bonn, DE"},"quantity":{"type":"integer","example":1},"prefix":{"type":["string","null"],"description":"Dial prefix in E.164 (country + area code if applicable).","example":"+49228"},"numbers":{"type":"array","description":"E.164-formatted numbers assigned to this order. Empty (`[]`) until the\norder reaches `success` - they are never returned synchronously by\n`POST \/numbers\/orders` (which only ever returns `requested`); they arrive\nlater via the webhook and then appear here on `GET \/numbers\/orders\/{id}`.\n","items":{"type":"string"},"example":["+4922812345678"]},"phone_numbers":{"type":"array","description":"The assigned numbers, in the same shape as `GET \/numbers`\n(id, number, name, is_active, call_flow), so you can read each number's id\nand current call flow and act on it directly (e.g. `PUT \/numbers\/{id}\/call-flow`).\nPopulated once the order reaches `success`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"error_message":{"type":["string","null"],"description":"Short error reason when status is `error` or `submission_failed`."},"webhook_url":{"type":["string","null"],"description":"The webhook URL we will POST the final outcome to."},"webhook_status":{"type":"string","enum":["not_required","pending","retrying","delivered","failed","cancelled"]},"webhook_next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Order not found in the caller's PBX."}}},"post":{"tags":["Numbers"],"summary":"Edit and retry a failed phone number order","operationId":"updatePhoneNumberOrder","security":[{"IntegrationApiKey":[]}],"description":"Edit selected fields of a `submission_failed` order and re-submit it\nupstream. Same multipart contract as `POST \/numbers\/orders`.\n\nUses `POST` (not `PUT`) on purpose: the body is `multipart\/form-data`, and\nmany server runtimes only parse a multipart body when the method is `POST` -\non `PUT` the fields and files arrive empty. Send this edit as a plain `POST`.\n\nConstraints:\n- Only orders with status `submission_failed` can be edited.\n- `country` is frozen. You may re-send it with the same value (handy when\n  you echo back the whole order), but *changing* it returns `422` - order in\n  a different country by creating a new order. Omitting it is also fine.\n\n`customer_name` and `order_id` are editable here: send new values to change\nthem, or send an empty `order_id` to clear your reference.\n\nIf the edited address yields different KYC requirements upstream, the\nresponse will be `422` carrying the new requirements; resubmit again with\nthe matching KYC fields.\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"type":"object","required":["customer_name","street","street_number","postal_code","city","quantity"],"properties":{"customer_name":{"type":"string","maxLength":255,"description":"Legal name of the customer. Required and editable on retry;\nforwarded to the carrier, which may validate it.\n","example":"ACME GmbH"},"street":{"type":"string"},"street_number":{"type":"string"},"postal_code":{"type":"string"},"city":{"type":"string"},"area_code":{"type":["string","null"],"maxLength":16,"description":"Country-conditional. Required when the order's (locked) country\nneeds it - e.g. Switzerland (`CH`), where it would be something like\n`43` - and rejected (422) otherwise.\n","example":null},"quantity":{"type":"integer","minimum":1},"webhook":{"type":["string","null"],"format":"uri"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Optional customer reference (max 64 chars). Editable on retry -\nsend a new value to change it, or an empty string to clear it.\nEchoed back in the response, in `GET \/numbers\/orders\/{id}`, and\nat the top level of the asynchronous webhook payload as `order_id`\n(the webhook body is the same order object).\n","example":"po-2026-00042"},"kyc":{"type":"object","additionalProperties":true,"description":"KYC documents, one entry per `documentType` returned by\n`POST \/numbers\/orders\/check` for the country. Send file documents\nas a file part `kyc[<documentType>]` and identifier-only documents\nas a form field `kyc[<documentType>]=<value>`. Accepted file MIME\ntypes: `application\/pdf`, `image\/jpeg`, `image\/png`. Example shape:\n\n  * `kyc[utility_bill]` - file part carrying `bill.pdf`\n  * `kyc[id_document]` - file part carrying `passport.jpg`\n  * `kyc[business_registration_number]=BE-12345` - form field\n\nFor an OR group returned by the check endpoint (an array of types),\nprovide any one of the listed `documentType`s. Re-send the KYC\ndocuments you want on the retried order; on submission_failed\nretries the carrier re-validates them.\n"}}}}}},"responses":{"200":{"description":"Order re-submitted upstream successfully.","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Internal order id assigned by us. Use this with `GET \/numbers\/orders\/{id}`\nto fetch the latest state. NOT the value echoed in the asynchronous\nwebhook payload - that one is `order_id` (your own reference).\n","example":"550e8400-e29b-41d4-a716-446655440000"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Your customer reference, supplied via the `order_id` field in\n`POST \/numbers\/orders` (or `POST \/numbers\/orders\/{id}`). Echoed back here,\nin `GET \/numbers\/orders\/{id}`, and at the top level of the asynchronous\nwebhook payload (which is this same object) as `order_id`.\n","example":"po-2026-00042"},"customer_name":{"type":"string","description":"Legal name of the customer the numbers were ordered for, as supplied on\ncreate (and editable on retry).\n","example":"ACME GmbH"},"status":{"type":"string","enum":["created","requested","submission_failed","processing","success","error","processing_failed"],"description":"Lifecycle state of this order.\n * `requested`: sent upstream, awaiting fulfilment.\n * `submission_failed`: rejected during synchronous submission; editable + retryable.\n * `processing`: async success callback received; provisioning in progress.\n * `success`: provisioning complete; `numbers` is populated.\n * `error`: async rejection; terminal.\n * `processing_failed`: internal processing exhausted retries; admin-only retry.\n","example":"requested"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"description":"Country-conditional (e.g. set for CH); null otherwise.","example":null},"country":{"type":"string","example":"DE"}}},"formatted_address":{"type":["string","null"],"description":"Single-line, comma-separated address derived from the persisted\ncomponents (street + number, postal code + city, country). Empty\ncomponents are dropped.\n","example":"Adenauerallee 1, 53113 Bonn, DE"},"quantity":{"type":"integer","example":1},"prefix":{"type":["string","null"],"description":"Dial prefix in E.164 (country + area code if applicable).","example":"+49228"},"numbers":{"type":"array","description":"E.164-formatted numbers assigned to this order. Empty (`[]`) until the\norder reaches `success` - they are never returned synchronously by\n`POST \/numbers\/orders` (which only ever returns `requested`); they arrive\nlater via the webhook and then appear here on `GET \/numbers\/orders\/{id}`.\n","items":{"type":"string"},"example":["+4922812345678"]},"phone_numbers":{"type":"array","description":"The assigned numbers, in the same shape as `GET \/numbers`\n(id, number, name, is_active, call_flow), so you can read each number's id\nand current call flow and act on it directly (e.g. `PUT \/numbers\/{id}\/call-flow`).\nPopulated once the order reaches `success`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"error_message":{"type":["string","null"],"description":"Short error reason when status is `error` or `submission_failed`."},"webhook_url":{"type":["string","null"],"description":"The webhook URL we will POST the final outcome to."},"webhook_status":{"type":"string","enum":["not_required","pending","retrying","delivered","failed","cancelled"]},"webhook_next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The order was created from a different source (e.g. the Cockpit UI) and\ncannot be retried via the API. Not field-specific, so the body is just a\n`message`.\n","content":{"application\/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"This order was not created via the API; retries must be initiated from the Cockpit UI."}}}},"404":{"description":"Order not found in the caller's PBX."},"409":{"description":"The order is not in `submission_failed` state, so it cannot be edited or\nretried. Not field-specific, so the body is just a `message` (the current\nstatus is included in it).\n","content":{"application\/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"Only orders with status submission_failed can be edited and retried (current status: requested)."}}}},"422":{"description":"Validation failed. `errors` maps each rejected field to its messages\n(including an attempt to *change* the locked `country`).\n\nIf the carrier rejected the retried order, it stays as a retryable\n`submission_failed` order and is returned in `data` (the full order, same\nshape as `GET \/numbers\/orders\/{id}`); use `data.id` to edit + retry it via\n`POST \/numbers\/orders\/{id}`. When `data` is absent, the failure was local\nvalidation only.\n","content":{"application\/json":{"schema":{"type":"object","required":["message","errors"],"additionalProperties":false,"properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"data":{"description":"Present only for a carrier rejection (a retryable order was\npersisted). The full order - same shape as\n`GET \/numbers\/orders\/{id}` - whose `id` you pass to\n`POST \/numbers\/orders\/{id}` to edit + retry. Absent for local\nvalidation errors.\n","allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Internal order id assigned by us. Use this with `GET \/numbers\/orders\/{id}`\nto fetch the latest state. NOT the value echoed in the asynchronous\nwebhook payload - that one is `order_id` (your own reference).\n","example":"550e8400-e29b-41d4-a716-446655440000"},"order_id":{"type":["string","null"],"maxLength":64,"description":"Your customer reference, supplied via the `order_id` field in\n`POST \/numbers\/orders` (or `POST \/numbers\/orders\/{id}`). Echoed back here,\nin `GET \/numbers\/orders\/{id}`, and at the top level of the asynchronous\nwebhook payload (which is this same object) as `order_id`.\n","example":"po-2026-00042"},"customer_name":{"type":"string","description":"Legal name of the customer the numbers were ordered for, as supplied on\ncreate (and editable on retry).\n","example":"ACME GmbH"},"status":{"type":"string","enum":["created","requested","submission_failed","processing","success","error","processing_failed"],"description":"Lifecycle state of this order.\n * `requested`: sent upstream, awaiting fulfilment.\n * `submission_failed`: rejected during synchronous submission; editable + retryable.\n * `processing`: async success callback received; provisioning in progress.\n * `success`: provisioning complete; `numbers` is populated.\n * `error`: async rejection; terminal.\n * `processing_failed`: internal processing exhausted retries; admin-only retry.\n","example":"requested"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Adenauerallee"},"street_number":{"type":"string","example":"1"},"postal_code":{"type":"string","example":"53113"},"city":{"type":"string","example":"Bonn"},"area_code":{"type":["string","null"],"description":"Country-conditional (e.g. set for CH); null otherwise.","example":null},"country":{"type":"string","example":"DE"}}},"formatted_address":{"type":["string","null"],"description":"Single-line, comma-separated address derived from the persisted\ncomponents (street + number, postal code + city, country). Empty\ncomponents are dropped.\n","example":"Adenauerallee 1, 53113 Bonn, DE"},"quantity":{"type":"integer","example":1},"prefix":{"type":["string","null"],"description":"Dial prefix in E.164 (country + area code if applicable).","example":"+49228"},"numbers":{"type":"array","description":"E.164-formatted numbers assigned to this order. Empty (`[]`) until the\norder reaches `success` - they are never returned synchronously by\n`POST \/numbers\/orders` (which only ever returns `requested`); they arrive\nlater via the webhook and then appear here on `GET \/numbers\/orders\/{id}`.\n","items":{"type":"string"},"example":["+4922812345678"]},"phone_numbers":{"type":"array","description":"The assigned numbers, in the same shape as `GET \/numbers`\n(id, number, name, is_active, call_flow), so you can read each number's id\nand current call flow and act on it directly (e.g. `PUT \/numbers\/{id}\/call-flow`).\nPopulated once the order reaches `success`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"number":{"type":"string","description":"Phone number in E.164 format.","example":"+12125550100"},"name":{"type":["string","null"],"example":"Customer Support"},"is_active":{"type":"boolean","example":true},"call_flow_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440100"},"call_flow":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}}}},"error_message":{"type":["string","null"],"description":"Short error reason when status is `error` or `submission_failed`."},"webhook_url":{"type":["string","null"],"description":"The webhook URL we will POST the final outcome to."},"webhook_status":{"type":"string","enum":["not_required","pending","retrying","delivered","failed","cancelled"]},"webhook_next_retry_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}]}}},"examples":{"validationError":{"summary":"Local validation - one or more fields invalid","value":{"message":"The street field is required. (and 4 more errors)","errors":{"customer_name":["The customer name field is required."],"street":["The street field is required."],"street_number":["The street number field is required."],"postal_code":["The postal code field is required."],"city":["The city field is required."],"area_code":["The area code field is required."],"quantity":["The quantity field must be at least 1."],"country":["Country cannot be changed - create a new request if you need to order in a different country."],"order_id":["The order id field must not be greater than 64 characters."]}}},"carrierRejection":{"summary":"Carrier rejected the retried order (mapped to your fields)","value":{"message":"This value is too short. It should have 3 characters or more. (and 1 more error)","errors":{"customer_name":["This value is too short. It should have 3 characters or more."],"city":["The city does not match the provided postal code."]},"data":{"id":"550e8400-e29b-41d4-a716-446655440000","order_id":"po-2026-00042","customer_name":"ACME GmbH","status":"submission_failed","address":{"street":"Adenauerallee","street_number":"1","postal_code":"53113","city":"Bonn","area_code":null,"country":"DE"},"formatted_address":"Adenauerallee 1, 53113 Bonn, DE","quantity":1,"prefix":null,"numbers":[],"phone_numbers":[],"error_message":"Nexus rejected the request with status 422","webhook_url":"https:\/\/your-app.example\/hooks\/number-order","webhook_status":"not_required","webhook_next_retry_at":null,"created_at":"2026-05-12T10:36:47+00:00","updated_at":"2026-05-12T11:02:13+00:00"}}}}}}}}}},"\/push-configuration":{"post":{"tags":["Push configuration"],"summary":"Push the PBX configuration (pbx)","operationId":"postPushConfiguration","description":"Push the authenticated PBX's configuration so that pending changes take\neffect. This is the programmatic equivalent of the \"Push configuration\"\nbutton in Cockpit, typically called after a number's call flow has been\nchanged.\n\nThe target PBX is derived from the API key; there is no request body.\n\nThe presented PBX API key must carry the `push_configuration`\nability\/scope.\n\n**Rate limit:** 1 request per minute per PBX. Exceeding the limit returns\n`429` with a `Retry-After` header.\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"200":{"description":"Configuration push recorded.","content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"pushed"},"pushed_at":{"type":"string","description":"When the push was recorded, in the PBX timezone.","example":"2026-06-15 09:12:04"}}},"example":{"status":"pushed","pushed_at":"2026-06-15 09:12:04"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The presented PBX API key does not carry the required\n`push_configuration` ability\/scope.\n"},"409":{"description":"Configuration pushes are currently locked for this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"push_configuration_locked"},"message":{"type":"string","example":"Configuration pushes are currently locked for this PBX."}}},"example":{"error":"push_configuration_locked","message":"Configuration pushes are currently locked for this PBX."}}}},"429":{"description":"Rate limit exceeded (max 1 push per minute per PBX). Wait `Retry-After`\nseconds before retrying.\n","headers":{"Retry-After":{"description":"Seconds to wait before the next allowed request.","schema":{"type":"integer","example":46}},"X-RateLimit-Limit":{"description":"Maximum requests allowed in the window (1).","schema":{"type":"integer","example":1}},"X-RateLimit-Remaining":{"description":"Requests remaining in the window (0 while throttled).","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp when the window resets.","schema":{"type":"integer","example":1781265182}}}},"500":{"description":"The push could not be recorded; retry later.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"push_failed"},"message":{"type":"string","example":"Could not push the configuration. Please try again later."}}},"example":{"error":"push_failed","message":"Could not push the configuration. Please try again later."}}}}}}},"\/odoo-installer\/register-install":{"post":{"tags":["OdooInstaller"],"summary":"Register an Odoo installation (pbx)","operationId":"postOdooInstallerRegisterInstall","description":"Registers (upserts) the Odoo integration for the authenticated PBX and queues the\ninstallation job. Consumed by the Voxbi Installer module running inside a customer's\nOdoo. The PBX is resolved from the API key, so it is never part of the request body.\nRequires an API key carrying the `odoo-installer` ability.\n","security":[{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["odoo_url","odoo_db","odoo_version","service_user","service_key","service_uid"],"properties":{"odoo_url":{"type":"string","maxLength":255,"description":"Base URL of the customer's Odoo instance.","example":"https:\/\/erp.example.com"},"odoo_db":{"type":"string","maxLength":128,"example":"example_prod"},"odoo_version":{"type":"string","maxLength":16,"example":"17.0"},"service_user":{"type":"string","maxLength":128,"description":"Login of the Odoo service account.","example":"svc_voxbi"},"service_key":{"type":"string","maxLength":255,"writeOnly":true,"description":"Odoo service account API key. Stored encrypted and never returned.","example":"s3cr3t-service-key"},"service_uid":{"type":"integer","description":"Numeric Odoo user id of the service account.","example":7},"sync_sip_configurations":{"type":"boolean","default":false,"description":"When true, SIP configurations are pushed to Odoo VoIP.","example":true},"is_active":{"type":"boolean","default":true,"example":true},"installer_module_version":{"type":"string","maxLength":32,"example":"1.2.0"}}},"example":{"odoo_url":"https:\/\/erp.example.com","odoo_db":"example_prod","odoo_version":"17.0","service_user":"svc_voxbi","service_key":"s3cr3t-service-key","service_uid":7,"sync_sip_configurations":true,"is_active":true,"installer_module_version":"1.2.0"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created. The integration is registered and the install job is queued.","content":{"application\/json":{"schema":{"type":"object","properties":{"integration_id":{"type":"string","format":"uuid"},"status_url":{"type":"string","format":"uri","description":"Poll this URL for the install status."}}},"example":{"integration_id":"550e8400-e29b-41d4-a716-446655440000","status_url":"https:\/\/cockpit.voxbi.com\/api\/v1\/odoo-installer\/install-status"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/odoo-installer\/install-status":{"get":{"tags":["OdooInstaller"],"summary":"Get the Odoo installation status (pbx)","operationId":"getOdooInstallerInstallStatus","description":"Returns the current install job status for the authenticated PBX's Odoo integration.\nRequires an API key carrying the `odoo-installer` ability.\n","security":[{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","processing","success","failed"],"description":"Current install job status."},"results":{"type":"array","description":"Per-step results of the install job. Empty until the job runs.","items":{"type":"object"}},"updated_at":{"type":["string","null"],"format":"date-time"}}},"example":{"status":"pending","results":[],"updated_at":"2026-06-01T08:29:07+00:00"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"No Odoo integration exists for the authenticated PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}},"example":{"error":"not_found"}}}}}}},"\/odoo-installer\/get-integration":{"get":{"tags":["OdooInstaller"],"summary":"Get the Odoo integration (pbx)","operationId":"getOdooInstallerGetIntegration","description":"Returns the Odoo integration record for the authenticated PBX. The service account\nAPI key is never returned. Requires an API key carrying the `odoo-installer` ability.\n","security":[{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"integration_id":{"type":"string","format":"uuid"},"pbx_id":{"type":"string","format":"uuid"},"type":{"type":"string","example":"odoo"},"is_active":{"type":"boolean"},"job_status":{"type":"string","enum":["pending","processing","success","failed"]},"odoo_url":{"type":["string","null"]},"odoo_db":{"type":["string","null"]},"service_user":{"type":["string","null"]},"odoo_version":{"type":["string","null"]},"sync_sip_configurations":{"type":"boolean"},"updated_at":{"type":["string","null"],"format":"date-time"}}},"example":{"integration_id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","type":"odoo","is_active":true,"job_status":"success","odoo_url":"https:\/\/erp.example.com","odoo_db":"example_prod","service_user":"svc_voxbi","odoo_version":"17.0","sync_sip_configurations":true,"updated_at":"2026-06-01T08:29:07+00:00"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"No Odoo integration exists for the authenticated PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}},"example":{"error":"not_found"}}}}}}},"\/odoo-installer\/update-and-fix-integration":{"post":{"tags":["OdooInstaller"],"summary":"Update and re-run the Odoo integration (pbx)","operationId":"postOdooInstallerUpdateAndFixIntegration","description":"Patches the supplied fields on the authenticated PBX's Odoo integration and re-queues\nthe install job (job status is reset to `pending` and previous results are cleared).\nEvery field is optional; only the fields you send are changed. The PBX is resolved\nfrom the API key. Requires an API key carrying the `odoo-installer` ability.\n","security":[{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","properties":{"odoo_url":{"type":"string","maxLength":255,"example":"https:\/\/erp.example.com"},"odoo_db":{"type":"string","maxLength":128,"example":"example_prod"},"odoo_version":{"type":"string","maxLength":16,"example":"17.0"},"service_user":{"type":"string","maxLength":128,"example":"svc_voxbi"},"service_key":{"type":"string","maxLength":255,"writeOnly":true,"description":"Odoo service account API key. Stored encrypted and never returned.","example":"s3cr3t-service-key"},"service_uid":{"type":"integer","example":7},"sync_sip_configurations":{"type":"boolean","example":true},"is_active":{"type":"boolean","example":true},"installer_module_version":{"type":"string","maxLength":32,"example":"1.2.0"}}},"example":{"odoo_version":"17.0","is_active":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The integration was updated and the install job re-queued.","content":{"application\/json":{"schema":{"type":"object","properties":{"integration_id":{"type":"string","format":"uuid"},"job_status":{"type":"string","enum":["pending"],"description":"Always reset to `pending` on save."},"status_url":{"type":"string","format":"uri"}}},"example":{"integration_id":"550e8400-e29b-41d4-a716-446655440000","job_status":"pending","status_url":"https:\/\/cockpit.voxbi.com\/api\/v1\/odoo-installer\/install-status"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"No Odoo integration exists for the authenticated PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}},"example":{"error":"not_found"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/phone-numbers":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["PhoneNumbers"],"summary":"List Phone number","operationId":"listPhoneNumbers","description":"Returns a paginated list of phone numbers. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `number`, `is_active`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"External DID owned by the PBX. The optional `handling_strategy` JSON column\ncarries the inbound routing for the number (the previous top-level\n`prefix_to_add`\/`prefix_to_remove`\/`routing` fields live inside it now).\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Phone number identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_carrier_id":{"type":["string","null"],"format":"uuid","description":"Default outbound SIP carrier for calls placed via this number","example":"550e8400-e29b-41d4-a716-446655440002"},"fallback_carrier_id":{"type":["string","null"],"format":"uuid","description":"Fallback SIP carrier used when the default carrier is unreachable","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"maxLength":64,"description":"Human-readable label for the number","example":"Support line"},"language":{"type":["string","null"],"description":"Announcement language for calls to this number (channel language). `null`\ninherits the system default; ISO-639-1 code otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"number":{"type":"string","maxLength":15,"description":"Phone number in E.164 (without leading +) or local format","example":"12125550100"},"international_prefix":{"type":["string","null"],"maxLength":15,"description":"International dialling prefix associated with the number","example":"1"},"is_root":{"type":"boolean","description":"Whether this DID is a root number (parent of suffixed CIDs)","example":true},"is_active":{"type":"boolean","description":"Whether the number is provisioned and routable","example":true},"sync_source":{"type":"string","description":"Provisioning origin of this number","enum":["manual","provision"],"example":"manual"},"handling_strategy":{"type":["object","null"],"description":"Optional inbound routing configuration. `type` discriminates the shape\nof `config`.\n","properties":{"type":{"type":"string","enum":["default","rewrite","call_flow","extension","user","sip_device"],"example":"call_flow"},"default_callflow_id":{"type":["string","null"],"format":"uuid"},"no_ext_match_callflow_id":{"type":["string","null"],"format":"uuid"},"prefix_to_remove":{"type":["string","null"]},"prefix_to_add":{"type":["string","null"]},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"number_and_name":{"type":"string","description":"Convenience label combining the number and its name","example":"12125550100 (Support line)","readOnly":true},"number_without_international_prefix":{"type":"string","description":"The number with its international prefix stripped","example":"2125550100","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/phone-numbers\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["PhoneNumbers"],"summary":"Find Phone number by ID","operationId":"getPhoneNumber","description":"Returns the phone number identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"External DID owned by the PBX. The optional `handling_strategy` JSON column\ncarries the inbound routing for the number (the previous top-level\n`prefix_to_add`\/`prefix_to_remove`\/`routing` fields live inside it now).\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Phone number identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_carrier_id":{"type":["string","null"],"format":"uuid","description":"Default outbound SIP carrier for calls placed via this number","example":"550e8400-e29b-41d4-a716-446655440002"},"fallback_carrier_id":{"type":["string","null"],"format":"uuid","description":"Fallback SIP carrier used when the default carrier is unreachable","example":"550e8400-e29b-41d4-a716-446655440003"},"name":{"type":["string","null"],"maxLength":64,"description":"Human-readable label for the number","example":"Support line"},"language":{"type":["string","null"],"description":"Announcement language for calls to this number (channel language). `null`\ninherits the system default; ISO-639-1 code otherwise.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"number":{"type":"string","maxLength":15,"description":"Phone number in E.164 (without leading +) or local format","example":"12125550100"},"international_prefix":{"type":["string","null"],"maxLength":15,"description":"International dialling prefix associated with the number","example":"1"},"is_root":{"type":"boolean","description":"Whether this DID is a root number (parent of suffixed CIDs)","example":true},"is_active":{"type":"boolean","description":"Whether the number is provisioned and routable","example":true},"sync_source":{"type":"string","description":"Provisioning origin of this number","enum":["manual","provision"],"example":"manual"},"handling_strategy":{"type":["object","null"],"description":"Optional inbound routing configuration. `type` discriminates the shape\nof `config`.\n","properties":{"type":{"type":"string","enum":["default","rewrite","call_flow","extension","user","sip_device"],"example":"call_flow"},"default_callflow_id":{"type":["string","null"],"format":"uuid"},"no_ext_match_callflow_id":{"type":["string","null"],"format":"uuid"},"prefix_to_remove":{"type":["string","null"]},"prefix_to_add":{"type":["string","null"]},"call_flow_id":{"type":["string","null"],"format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"sip_device_id":{"type":["string","null"],"format":"uuid"}}},"number_and_name":{"type":"string","description":"Convenience label combining the number and its name","example":"12125550100 (Support line)","readOnly":true},"number_without_international_prefix":{"type":"string","description":"The number with its international prefix stripped","example":"2125550100","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/register-device":{"post":{"tags":["Users"],"summary":"Register a device for push notifications","operationId":"postPushNotificationRegister","description":"Creates a new push notification register. Validation rules and required fields are defined\nin the request body schema below.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["token","platform"],"properties":{"token":{"type":"string","description":"Device push notification token","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},"platform":{"type":"string","description":"Device platform (ios, android, web)","example":"ios"}}},"example":{"token":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]","platform":"ios"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"success","message":"Device registered for push notifications."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/unregister-device":{"post":{"tags":["Users"],"summary":"Unregister a device from push notifications","operationId":"postPushNotificationUnregister","description":"Creates a new push notification unregister. Validation rules and required fields are defined\nin the request body schema below.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Device push notification token to unregister","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"}}},"example":{"token":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"success","message":"Device unregistered."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/cleanup-old-tokens":{"post":{"tags":["Users"],"summary":"Clean up old push notification tokens","operationId":"postPushNotificationCleanup","description":"Triggers the action on the targeted push notification cleanup.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"},"removed":{"type":"integer","description":"Number of tokens removed"}}},"example":{"status":"success","message":"Old tokens cleaned up.","removed":5}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/notify-device":{"post":{"tags":["Users"],"summary":"Send a push notification to a device","operationId":"postPushNotificationNotifyDevice","security":[{"PbxServerAuth":[]}],"description":"Creates a new push notification notify device. Validation rules and required fields are\ndefined in the request body schema below.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Device push notification token","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},"title":{"type":"string","description":"Notification title","example":"Incoming Call"},"body":{"type":"string","description":"Notification body","example":"John Doe is calling you"},"data":{"type":"object","description":"Additional notification payload data","additionalProperties":true}}},"example":{"token":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]","title":"Incoming Call","body":"John Doe is calling you"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"example":{"status":"success","message":"Notification sent."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/queues":{"get":{"tags":["Queues"],"summary":"List queue","operationId":"listQueues","description":"Returns a paginated list of queues. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, pbx_id, pool_id, name, ring_strategy, music_on_hold_id, ring_busy_members, ring_twinnings, ring_duration, interval, wrap_up_time, exit_key, ring_empty, weight, mapping_id, voip_queue_id and call_flow_id.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Call queue distributes inbound calls across a set of member agents according\nto a ring strategy. Callers wait while music-on-hold plays, and a member is\nconnected once one becomes available.\n\nThis schema documents the fields returned by the V1 API (the `responseAttributes`\nprojection of the Queue model), not the full database row. Timing fields are:\n`ring_duration` (how long each agent is rung), `interval` (gap between ring\nattempts), and `wrap_up_time` (post-call cool-down before the agent is rung\nagain). Queue membership is exposed inline through `users`; groups and pools\nare managed via separate endpoints and are not part of this projection.\n","required":["id","pbx_id","name","ring_strategy","ring_busy_members","ring_duration","interval","wrap_up_time","ring_empty","enable_caller_position","caller_position_announce_frequency","caller_position_language","users"],"properties":{"id":{"type":"string","format":"uuid","description":"Queue identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant) that owns this queue","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":128,"description":"Human-readable name of the queue","example":"Customer Support"},"ring_strategy":{"type":"string","description":"Order in which queue members are rung when a call arrives. `ring_all`\nrings every member at once; `round_robin` cycles through members in turn;\n`least_recent` favours the member idle the longest; `fewest_calls` favours\nthe member who has taken the fewest calls; `random` picks at random.\n","enum":["fewest_calls","least_recent","round_robin","ring_all","random"],"example":"ring_all"},"ring_busy_members":{"type":"boolean","description":"Whether members already on a call are still rung for new queue calls","example":false},"ring_duration":{"type":"integer","format":"int32","minimum":-1,"description":"Seconds to ring a member before moving on to the next; -1 means unlimited","example":20},"interval":{"type":"integer","format":"int32","minimum":0,"description":"Seconds to wait between successive ring attempts (0 means no wait)","example":5},"wrap_up_time":{"type":"integer","format":"int32","minimum":0,"description":"Seconds an agent stays unavailable after finishing a queue call (0 means no wait)","example":30},"exit_key":{"type":["string","null"],"description":"DTMF key a waiting caller can press to leave the queue and follow the\nattached call flow. Null when no exit key is configured.\n","enum":["0","1","2","3","4","5","6","7","8","9","*","#"],"example":"0"},"ring_empty":{"type":"boolean","description":"Whether callers may enter (and the queue keeps ringing) even when no members are available","example":false},"enable_caller_position":{"type":"boolean","description":"Whether waiting callers hear periodic announcements of their position in the queue","example":false},"caller_position_announce_frequency":{"type":"integer","format":"int32","minimum":0,"description":"How often, in seconds, a waiting caller's position and\/or estimated hold time is announced","example":10},"caller_position_language":{"type":"string","description":"Language used for the caller position announcement","enum":["en","de","fr"],"example":"en"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file (of type `music`) played to callers while\nthey wait. Null when no music-on-hold is configured.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"users":{"type":"array","description":"Queue member users, ordered by the tenant's configured name preference.\nEach item is a User resource. The array is empty when no users are\nassigned to the queue.\n","items":{"type":"object","description":"PBX user. Each user belongs to exactly one Pbx, owns optional extensions\nand devices, and carries a large set of feature flags controlling what they\ncan do in the Voxbi UI and on the telephony stack.\n\nSecrets and credentials are never exposed through the API. Relation keys are\nopt-in via `?include=`.\n","required":["id","pbx_id","first_name","email","status"],"properties":{"id":{"type":"string","format":"uuid","description":"User identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"first_name":{"type":"string","maxLength":64,"example":"Jane"},"last_name":{"type":["string","null"],"maxLength":64,"example":"Smith"},"name":{"type":"string","readOnly":true,"description":"Combined display name (accessor, respects PBX formatting settings)","example":"Jane Smith"},"full_name_with_email":{"type":"string","readOnly":true,"description":"Convenience label combining the display name and email","example":"Jane Smith <jane.smith@example.com>"},"email":{"type":"string","format":"email","maxLength":100,"example":"jane.smith@example.com"},"status":{"type":"string","enum":["enabled","disabled"],"example":"enabled"},"type":{"type":"string","description":"User category","enum":["user","pickup_line"],"example":"user"},"language":{"type":"string","description":"Preferred UI language","enum":["en","de","fr"],"example":"en"},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import","microsoft_entra"],"example":"manual"},"vip":{"type":"boolean","description":"Whether the user is flagged as VIP","example":false},"show_in_address_book":{"type":"boolean","description":"Whether the user appears in the shared address book","example":true},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default outbound CID for this user","example":"550e8400-e29b-41d4-a716-446655440004"},"caller_identity_internal_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the internal caller ID","example":"550e8400-e29b-41d4-a716-446655440002"},"caller_identity_external_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the external caller ID","example":"550e8400-e29b-41d4-a716-446655440003"},"allow_telephony":{"type":"boolean","description":"Whether the user can place and receive calls","example":true},"allow_call_forwarding":{"type":"boolean","example":true},"allow_change_twinning_dest":{"type":"boolean","description":"Whether the user may change their twinning destination","example":true},"allow_dnd":{"type":"boolean","description":"Whether the user may set their own Do Not Disturb","example":true},"allow_status_changer":{"type":"boolean","description":"Whether the user may change other users' statuses","example":false},"allow_anonymous_calls":{"type":"boolean","description":"Whether the user is allowed to place anonymous outbound calls","example":false},"allow_international_calls":{"type":"boolean","example":false},"allow_eu_calls":{"type":"boolean","example":true},"allow_national_calls":{"type":"boolean","example":true},"allow_premium_numbers":{"type":"boolean","example":false},"allow_sms":{"type":"boolean","example":false},"allow_manage_global_contacts":{"type":"boolean","example":false},"allow_manage_voicemail_parameters":{"type":"boolean","example":true},"allow_in_call_recording":{"type":"boolean","description":"Whether the user can start\/stop recording during a call","example":false},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable by this user","example":true},"allow_grafana_access":{"type":"boolean","description":"Whether the user can access the Grafana dashboards","example":false},"allow_right_to_disconnect":{"type":"boolean","description":"Whether the user may set their own right-to-disconnect schedule","example":true},"right_to_disconnect":{"type":"boolean","description":"Whether the right-to-disconnect rule is currently enforced","example":false},"concurrent_calls":{"type":"boolean","description":"Whether the user may have multiple simultaneous calls","example":true},"extension_roaming":{"type":"boolean","description":"Whether the user may hot-desk by logging into other devices","example":true},"record_your_calls":{"type":"boolean","description":"Default per-call recording flag for outbound external calls","example":false},"record_your_internal_calls":{"type":"integer","description":"Tri-state flag controlling internal-call recording (0 = off, 1 = on,\n2 = follow PBX default). Stored as an integer despite the boolean-style\nname.\n","example":2},"access_all_call_recordings":{"type":"boolean","description":"Whether the user may access call recordings of others","example":false},"call_recordings_visibility":{"type":"string","enum":["all_calls","own_calls_only"],"example":"own_calls_only"},"call_information_visibility":{"type":"string","enum":["none","own_calls","own_group_only"],"example":"own_calls"},"send_missed_call_via_email":{"type":"boolean","example":true},"limit_email_missed_call_to_direct":{"type":"boolean","description":"Whether missed-call emails are limited to directly-dialled calls","example":false},"show_caller_id_for_twinning_call":{"type":"integer","description":"Tri-state flag controlling caller-ID display on twinning calls (0 = off,\n1 = on, 2 = follow PBX default).\n","example":2},"voicemail_type":{"type":"string","description":"Voicemail mode","enum":["disabled","enabled","internal","external"],"example":"internal"},"voicemail_destination":{"type":"string","description":"Where voicemail notifications are sent","enum":["email_only","email_and_phone"],"example":"email_only"},"invited_at":{"type":["string","null"],"format":"date-time","description":"When the user was invited (if onboarding via invitation)","example":null},"accepted_invitation_at":{"type":["string","null"],"format":"date-time","description":"When the user accepted their invitation","example":null},"email_verified_at":{"type":["string","null"],"format":"date-time","example":"2024-02-15T10:00:00Z","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"extensions":{"type":"array","description":"Extensions owned by the user. Returned only when requested via `?include=extensions`.","items":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"groups":{"type":"array","description":"Groups the user belongs to. Returned only when requested via `?include=groups`.","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_manage_group_contacts":{"type":"array","description":"Groups whose contacts the user may manage. Returned only when requested\nvia `?include=allowManageGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_access_to_group_contacts":{"type":"array","description":"Groups whose contacts the user may access. Returned only when requested\nvia `?include=allowAccessToGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"sip_devices":{"type":"array","description":"SIP devices assigned to the user. Returned only when requested via `?include=sipDevices`.","items":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}},"twinnings":{"type":"array","description":"Twinnings configured for the user. Returned only when requested via `?include=twinnings`.","items":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Effective (inherited) caller identities for the user: own plus those of\nthe user's groups plus the PBX's. Returned only when requested via\n`?include=callerIdentities`.\n","items":{"type":"object"}},"locations":{"type":"array","description":"Locations the user is associated with. Returned only when requested via `?include=locations`.","items":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"languages":{"type":"array","description":"Languages the user is associated with. Returned only when requested via `?include=languages`.","items":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"tags":{"type":"array","description":"Tags attached to the user. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"queues":{"type":"array","description":"Queues the user is a member of. Returned only when requested via `?include=queues`.","items":{"type":"object"}}}}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/queues\/{id}":{"get":{"tags":["Queues"],"summary":"Get a Queue","operationId":"getQueue","description":"Returns the queue identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Call queue distributes inbound calls across a set of member agents according\nto a ring strategy. Callers wait while music-on-hold plays, and a member is\nconnected once one becomes available.\n\nThis schema documents the fields returned by the V1 API (the `responseAttributes`\nprojection of the Queue model), not the full database row. Timing fields are:\n`ring_duration` (how long each agent is rung), `interval` (gap between ring\nattempts), and `wrap_up_time` (post-call cool-down before the agent is rung\nagain). Queue membership is exposed inline through `users`; groups and pools\nare managed via separate endpoints and are not part of this projection.\n","required":["id","pbx_id","name","ring_strategy","ring_busy_members","ring_duration","interval","wrap_up_time","ring_empty","enable_caller_position","caller_position_announce_frequency","caller_position_language","users"],"properties":{"id":{"type":"string","format":"uuid","description":"Queue identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant) that owns this queue","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":128,"description":"Human-readable name of the queue","example":"Customer Support"},"ring_strategy":{"type":"string","description":"Order in which queue members are rung when a call arrives. `ring_all`\nrings every member at once; `round_robin` cycles through members in turn;\n`least_recent` favours the member idle the longest; `fewest_calls` favours\nthe member who has taken the fewest calls; `random` picks at random.\n","enum":["fewest_calls","least_recent","round_robin","ring_all","random"],"example":"ring_all"},"ring_busy_members":{"type":"boolean","description":"Whether members already on a call are still rung for new queue calls","example":false},"ring_duration":{"type":"integer","format":"int32","minimum":-1,"description":"Seconds to ring a member before moving on to the next; -1 means unlimited","example":20},"interval":{"type":"integer","format":"int32","minimum":0,"description":"Seconds to wait between successive ring attempts (0 means no wait)","example":5},"wrap_up_time":{"type":"integer","format":"int32","minimum":0,"description":"Seconds an agent stays unavailable after finishing a queue call (0 means no wait)","example":30},"exit_key":{"type":["string","null"],"description":"DTMF key a waiting caller can press to leave the queue and follow the\nattached call flow. Null when no exit key is configured.\n","enum":["0","1","2","3","4","5","6","7","8","9","*","#"],"example":"0"},"ring_empty":{"type":"boolean","description":"Whether callers may enter (and the queue keeps ringing) even when no members are available","example":false},"enable_caller_position":{"type":"boolean","description":"Whether waiting callers hear periodic announcements of their position in the queue","example":false},"caller_position_announce_frequency":{"type":"integer","format":"int32","minimum":0,"description":"How often, in seconds, a waiting caller's position and\/or estimated hold time is announced","example":10},"caller_position_language":{"type":"string","description":"Language used for the caller position announcement","enum":["en","de","fr"],"example":"en"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file (of type `music`) played to callers while\nthey wait. Null when no music-on-hold is configured.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"users":{"type":"array","description":"Queue member users, ordered by the tenant's configured name preference.\nEach item is a User resource. The array is empty when no users are\nassigned to the queue.\n","items":{"type":"object","description":"PBX user. Each user belongs to exactly one Pbx, owns optional extensions\nand devices, and carries a large set of feature flags controlling what they\ncan do in the Voxbi UI and on the telephony stack.\n\nSecrets and credentials are never exposed through the API. Relation keys are\nopt-in via `?include=`.\n","required":["id","pbx_id","first_name","email","status"],"properties":{"id":{"type":"string","format":"uuid","description":"User identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"first_name":{"type":"string","maxLength":64,"example":"Jane"},"last_name":{"type":["string","null"],"maxLength":64,"example":"Smith"},"name":{"type":"string","readOnly":true,"description":"Combined display name (accessor, respects PBX formatting settings)","example":"Jane Smith"},"full_name_with_email":{"type":"string","readOnly":true,"description":"Convenience label combining the display name and email","example":"Jane Smith <jane.smith@example.com>"},"email":{"type":"string","format":"email","maxLength":100,"example":"jane.smith@example.com"},"status":{"type":"string","enum":["enabled","disabled"],"example":"enabled"},"type":{"type":"string","description":"User category","enum":["user","pickup_line"],"example":"user"},"language":{"type":"string","description":"Preferred UI language","enum":["en","de","fr"],"example":"en"},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import","microsoft_entra"],"example":"manual"},"vip":{"type":"boolean","description":"Whether the user is flagged as VIP","example":false},"show_in_address_book":{"type":"boolean","description":"Whether the user appears in the shared address book","example":true},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default outbound CID for this user","example":"550e8400-e29b-41d4-a716-446655440004"},"caller_identity_internal_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the internal caller ID","example":"550e8400-e29b-41d4-a716-446655440002"},"caller_identity_external_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the external caller ID","example":"550e8400-e29b-41d4-a716-446655440003"},"allow_telephony":{"type":"boolean","description":"Whether the user can place and receive calls","example":true},"allow_call_forwarding":{"type":"boolean","example":true},"allow_change_twinning_dest":{"type":"boolean","description":"Whether the user may change their twinning destination","example":true},"allow_dnd":{"type":"boolean","description":"Whether the user may set their own Do Not Disturb","example":true},"allow_status_changer":{"type":"boolean","description":"Whether the user may change other users' statuses","example":false},"allow_anonymous_calls":{"type":"boolean","description":"Whether the user is allowed to place anonymous outbound calls","example":false},"allow_international_calls":{"type":"boolean","example":false},"allow_eu_calls":{"type":"boolean","example":true},"allow_national_calls":{"type":"boolean","example":true},"allow_premium_numbers":{"type":"boolean","example":false},"allow_sms":{"type":"boolean","example":false},"allow_manage_global_contacts":{"type":"boolean","example":false},"allow_manage_voicemail_parameters":{"type":"boolean","example":true},"allow_in_call_recording":{"type":"boolean","description":"Whether the user can start\/stop recording during a call","example":false},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable by this user","example":true},"allow_grafana_access":{"type":"boolean","description":"Whether the user can access the Grafana dashboards","example":false},"allow_right_to_disconnect":{"type":"boolean","description":"Whether the user may set their own right-to-disconnect schedule","example":true},"right_to_disconnect":{"type":"boolean","description":"Whether the right-to-disconnect rule is currently enforced","example":false},"concurrent_calls":{"type":"boolean","description":"Whether the user may have multiple simultaneous calls","example":true},"extension_roaming":{"type":"boolean","description":"Whether the user may hot-desk by logging into other devices","example":true},"record_your_calls":{"type":"boolean","description":"Default per-call recording flag for outbound external calls","example":false},"record_your_internal_calls":{"type":"integer","description":"Tri-state flag controlling internal-call recording (0 = off, 1 = on,\n2 = follow PBX default). Stored as an integer despite the boolean-style\nname.\n","example":2},"access_all_call_recordings":{"type":"boolean","description":"Whether the user may access call recordings of others","example":false},"call_recordings_visibility":{"type":"string","enum":["all_calls","own_calls_only"],"example":"own_calls_only"},"call_information_visibility":{"type":"string","enum":["none","own_calls","own_group_only"],"example":"own_calls"},"send_missed_call_via_email":{"type":"boolean","example":true},"limit_email_missed_call_to_direct":{"type":"boolean","description":"Whether missed-call emails are limited to directly-dialled calls","example":false},"show_caller_id_for_twinning_call":{"type":"integer","description":"Tri-state flag controlling caller-ID display on twinning calls (0 = off,\n1 = on, 2 = follow PBX default).\n","example":2},"voicemail_type":{"type":"string","description":"Voicemail mode","enum":["disabled","enabled","internal","external"],"example":"internal"},"voicemail_destination":{"type":"string","description":"Where voicemail notifications are sent","enum":["email_only","email_and_phone"],"example":"email_only"},"invited_at":{"type":["string","null"],"format":"date-time","description":"When the user was invited (if onboarding via invitation)","example":null},"accepted_invitation_at":{"type":["string","null"],"format":"date-time","description":"When the user accepted their invitation","example":null},"email_verified_at":{"type":["string","null"],"format":"date-time","example":"2024-02-15T10:00:00Z","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"extensions":{"type":"array","description":"Extensions owned by the user. Returned only when requested via `?include=extensions`.","items":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"groups":{"type":"array","description":"Groups the user belongs to. Returned only when requested via `?include=groups`.","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_manage_group_contacts":{"type":"array","description":"Groups whose contacts the user may manage. Returned only when requested\nvia `?include=allowManageGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_access_to_group_contacts":{"type":"array","description":"Groups whose contacts the user may access. Returned only when requested\nvia `?include=allowAccessToGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"sip_devices":{"type":"array","description":"SIP devices assigned to the user. Returned only when requested via `?include=sipDevices`.","items":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}},"twinnings":{"type":"array","description":"Twinnings configured for the user. Returned only when requested via `?include=twinnings`.","items":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Effective (inherited) caller identities for the user: own plus those of\nthe user's groups plus the PBX's. Returned only when requested via\n`?include=callerIdentities`.\n","items":{"type":"object"}},"locations":{"type":"array","description":"Locations the user is associated with. Returned only when requested via `?include=locations`.","items":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"languages":{"type":"array","description":"Languages the user is associated with. Returned only when requested via `?include=languages`.","items":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"tags":{"type":"array","description":"Tags attached to the user. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"queues":{"type":"array","description":"Queues the user is a member of. Returned only when requested via `?include=queues`.","items":{"type":"object"}}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/schedules":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Schedules"],"summary":"List schedule","operationId":"listSchedules","description":"Returns a paginated list of schedules. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `description`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Named schedule belonging to a single tenant (Pbx). A schedule groups a set of\ntime-of-day rules that downstream call flows reference to decide routing based\non the current date and time (for example, open versus closed hours). The\nactual rules live on the related `ScheduleStep` records (one schedule may\ncontain many steps covering days-of-the-week, fixed dates, recurring dates, or\nspecific periods); those steps are not embedded in this response and are\nretrieved through their own endpoints.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the schedule.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the owning tenant (Pbx). Every schedule is scoped to exactly one tenant.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":255,"description":"Human-readable label for the schedule, shown in the cockpit and used when selecting the schedule in call flows.","example":"Business hours"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note describing the purpose or coverage of the schedule. Null when no description was provided.","example":"Monday to Friday, 09:00 to 18:00"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the schedule was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the schedule was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/schedules\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Schedules"],"summary":"Get a Schedule","operationId":"getSchedule","description":"Returns the schedule identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Named schedule belonging to a single tenant (Pbx). A schedule groups a set of\ntime-of-day rules that downstream call flows reference to decide routing based\non the current date and time (for example, open versus closed hours). The\nactual rules live on the related `ScheduleStep` records (one schedule may\ncontain many steps covering days-of-the-week, fixed dates, recurring dates, or\nspecific periods); those steps are not embedded in this response and are\nretrieved through their own endpoints.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the schedule.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the owning tenant (Pbx). Every schedule is scoped to exactly one tenant.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","maxLength":255,"description":"Human-readable label for the schedule, shown in the cockpit and used when selecting the schedule in call flows.","example":"Business hours"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note describing the purpose or coverage of the schedule. Null when no description was provided.","example":"Monday to Friday, 09:00 to 18:00"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the schedule was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the schedule was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sip-carriers":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SipCarriers"],"summary":"List SIP carrier","operationId":"listSipCarriers","description":"Returns a paginated list of sip carriers. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `sip_user`, `sip_registrar`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Upstream SIP trunk used for outbound calls and number termination.\n","required":["id","pbx_id","sip_registrar"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP carrier identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"maxLength":128,"example":"Primary carrier"},"sip_user":{"type":["string","null"],"maxLength":64,"description":"SIP authentication username","example":"trunk_user"},"sip_registrar":{"type":"string","maxLength":64,"description":"SIP registrar hostname or IP","example":"sip.carrier.example.com"},"register":{"type":"boolean","description":"Whether the PBX registers against this carrier","example":true},"destination_header":{"type":"string","description":"SIP header consulted to determine the called party","enum":["default","p-called-party-id","to"],"example":"default"},"incoming_header":{"type":"string","description":"SIP header consulted to identify incoming calls","enum":["request-uri","to","contact"],"example":"request-uri"},"dtmf_mode":{"type":"string","description":"DTMF transport mode for calls through this carrier","enum":["info","rfc4733","inband","auto"],"example":"rfc4733"},"display_name":{"type":["string","null"],"description":"Convenience label combining the carrier name and registrar","example":"Primary carrier (sip.carrier.example.com)","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/sip-carriers\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SipCarriers"],"summary":"Get a sIP Carrier","operationId":"getSipCarrier","description":"Returns the sip carrier identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Upstream SIP trunk used for outbound calls and number termination.\n","required":["id","pbx_id","sip_registrar"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP carrier identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":["string","null"],"maxLength":128,"example":"Primary carrier"},"sip_user":{"type":["string","null"],"maxLength":64,"description":"SIP authentication username","example":"trunk_user"},"sip_registrar":{"type":"string","maxLength":64,"description":"SIP registrar hostname or IP","example":"sip.carrier.example.com"},"register":{"type":"boolean","description":"Whether the PBX registers against this carrier","example":true},"destination_header":{"type":"string","description":"SIP header consulted to determine the called party","enum":["default","p-called-party-id","to"],"example":"default"},"incoming_header":{"type":"string","description":"SIP header consulted to identify incoming calls","enum":["request-uri","to","contact"],"example":"request-uri"},"dtmf_mode":{"type":"string","description":"DTMF transport mode for calls through this carrier","enum":["info","rfc4733","inband","auto"],"example":"rfc4733"},"display_name":{"type":["string","null"],"description":"Convenience label combining the carrier name and registrar","example":"Primary carrier (sip.carrier.example.com)","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sip-devices":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SipDevices"],"summary":"List SIP device","operationId":"listSipDevices","description":"Returns a paginated list of sip devices. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `mac`, `sip_username`, `is_enabled`, `user_id`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"},{"name":"include","description":"Comma-separated related resources to embed (dot-nested where\nshown). Allowed: `target`, `tags`, `callerIdentities`, `location`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"target,tags"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/sip-devices\/{sip_device}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SipDevices"],"summary":"Get a sIP device","operationId":"getSipDevice","description":"Returns the sip device identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sip-devices\/inventory":{"get":{"tags":["SipDevices"],"summary":"Get SIP device inventory","operationId":"getSipDeviceInventory","description":"Returns a paginated list of sip device inventory. Use the standard `search`, `sort`, `page`,\nand `perPage` query parameters; use `filter[key]=value` to narrow the result set.\nMulti-tenant scoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"pbx_id":{"type":"integer"},"mac_address":{"type":"string"},"model":{"type":["string","null"]},"vendor":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":1,"pbx_id":1,"mac_address":"AA:BB:CC:DD:EE:FF","model":"Yealink T54W","vendor":"Yealink","status":"provisioned","created_at":"2023-10-16T08:29:07.000000Z","updated_at":"2023-10-16T08:29:07.000000Z"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/sound-files":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SoundFiles"],"summary":"List Sound file","operationId":"listSoundFiles","description":"Returns a paginated list of sound files. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `comment`, `type`, `source`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Audio asset used for greetings, prompts, music on hold, and voicemail.\nProtected\/built-in sound files have a `null` `pbx_id`. The raw audio payload\nis never inlined; instead `audio_url` is a short-lived signed URL to a\nstreaming endpoint.\n","required":["id","name","type","source"],"properties":{"id":{"type":"string","format":"uuid","description":"Sound file identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":["string","null"],"format":"uuid","description":"Pbx identifier (null for built-in\/protected files)","example":"550e8400-e29b-41d4-a716-446655440001"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default\/fallback announcement this record is a language\nvariant of. `null` for a top-level announcement. The list is flat and\nincludes variants: switch to a variant whose `language` matches the\ncaller's detected language, otherwise play the parent as the fallback.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Welcome announcement"},"comment":{"type":["string","null"],"maxLength":255,"example":"Played at the start of the main IVR"},"message":{"type":["string","null"],"description":"TTS source text (only populated when `source = ai_generated`)","example":"Welcome to Customer Support. Press 1 for sales, 2 for support."},"ai_voice_id":{"type":["string","null"],"description":"Identifier of the AI voice used to generate the audio","example":"voice_en_us_female_1"},"voice_settings":{"type":["object","null"],"description":"AI voice tuning settings (pitch, speed, etc.) as a JSON object","additionalProperties":true,"example":{"stability":0.75,"similarity_boost":0.5}},"source":{"type":"string","description":"Whether the audio was uploaded by the user or AI-generated","enum":["ai_generated","uploaded_file"],"example":"uploaded_file"},"type":{"type":"string","description":"Intended use category for the sound","enum":["announcement","music"],"example":"announcement"},"language":{"type":["string","null"],"description":"ISO-639-1 language of this announcement. Set on parents that have variants\nand on every variant; may be `null` on a plain standalone announcement.\nUsed by the PBX to match a variant to the caller's detected language.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"en"},"audio_url":{"type":"string","format":"uri","description":"Short-lived signed URL to a streaming endpoint for the audio. Plays\ndirectly in an <audio src> with no auth header and expires after a short\nwindow. The raw audio payload is never inlined in this response.\n","example":"https:\/\/api.example.com\/sound-files\/550e8400-e29b-41d4-a716-446655440000\/audio?signature=abc123&expires=1709280000","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/sound-files\/{soundFile}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["SoundFiles"],"summary":"Get a sound File","operationId":"getSoundFile","description":"Returns the sound file identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Audio asset used for greetings, prompts, music on hold, and voicemail.\nProtected\/built-in sound files have a `null` `pbx_id`. The raw audio payload\nis never inlined; instead `audio_url` is a short-lived signed URL to a\nstreaming endpoint.\n","required":["id","name","type","source"],"properties":{"id":{"type":"string","format":"uuid","description":"Sound file identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":["string","null"],"format":"uuid","description":"Pbx identifier (null for built-in\/protected files)","example":"550e8400-e29b-41d4-a716-446655440001"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the default\/fallback announcement this record is a language\nvariant of. `null` for a top-level announcement. The list is flat and\nincludes variants: switch to a variant whose `language` matches the\ncaller's detected language, otherwise play the parent as the fallback.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Welcome announcement"},"comment":{"type":["string","null"],"maxLength":255,"example":"Played at the start of the main IVR"},"message":{"type":["string","null"],"description":"TTS source text (only populated when `source = ai_generated`)","example":"Welcome to Customer Support. Press 1 for sales, 2 for support."},"ai_voice_id":{"type":["string","null"],"description":"Identifier of the AI voice used to generate the audio","example":"voice_en_us_female_1"},"voice_settings":{"type":["object","null"],"description":"AI voice tuning settings (pitch, speed, etc.) as a JSON object","additionalProperties":true,"example":{"stability":0.75,"similarity_boost":0.5}},"source":{"type":"string","description":"Whether the audio was uploaded by the user or AI-generated","enum":["ai_generated","uploaded_file"],"example":"uploaded_file"},"type":{"type":"string","description":"Intended use category for the sound","enum":["announcement","music"],"example":"announcement"},"language":{"type":["string","null"],"description":"ISO-639-1 language of this announcement. Set on parents that have variants\nand on every variant; may be `null` on a plain standalone announcement.\nUsed by the PBX to match a variant to the caller's detected language.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"en"},"audio_url":{"type":"string","format":"uri","description":"Short-lived signed URL to a streaming endpoint for the audio. Plays\ndirectly in an <audio src> with no auth header and expires after a short\nwindow. The raw audio payload is never inlined in this response.\n","example":"https:\/\/api.example.com\/sound-files\/550e8400-e29b-41d4-a716-446655440000\/audio?signature=abc123&expires=1709280000","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sound-files\/{soundFile}\/audio":{"get":{"tags":["SoundFiles"],"summary":"Stream a sound file's audio (user, pbx)","operationId":"getSoundFileAudio","description":"Stream the raw audio bytes of a sound file. The response is sent inline (not as\nan attachment) so it can be played directly, for example as the `src` of an\nHTML `<audio>` element. The `Content-Type` reflects the stored format\n(commonly `audio\/mpeg`, but `audio\/wav`, `audio\/flac` or `audio\/aac` may also\nbe returned), falling back to `audio\/mpeg`.\n\nThis endpoint accepts EITHER of two authentication methods:\n\n- A temporary signed URL. This is the `audio_url` returned by the sound file\n  resource (it embeds `expires` and `signature` query parameters and expires\n  roughly one hour after it is minted). No `Authorization` header is required,\n  which lets it be used directly in an `<audio src>`.\n- A bearer token carrying the `sound-files` ability. Used for durable or\n  programmatic access; the stream is scoped to the token principal's PBX.\n\nWhen neither a valid signature nor a token is present the request is rejected\nwith 401. A token that lacks the `sound-files` ability is rejected with 403.\n","security":[{"bearerAuth":[]},[]],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"audio\/mpeg"}},{"name":"soundFile","in":"path","required":true,"description":"Sound file identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"expires","in":"query","required":false,"description":"Expiry timestamp from the signed `audio_url`. Present only when authenticating with a signed URL.","schema":{"type":"integer","example":1709280000}},{"name":"signature","in":"query","required":false,"description":"HMAC signature from the signed `audio_url`. Present only when authenticating with a signed URL.","schema":{"type":"string","example":"abc123"}}],"responses":{"200":{"description":"Raw audio stream, sent inline.","headers":{"Content-Type":{"schema":{"type":"string","example":"audio\/mpeg"}},"Content-Disposition":{"schema":{"type":"string","example":"inline; filename=\"Welcome announcement\""}}},"content":{"audio\/mpeg":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The bearer token does not carry the `sound-files` ability."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sound-files\/{soundFileId}\/download":{"get":{"tags":["SoundFiles"],"summary":"Download a Sound File by ID","operationId":"getSoundFileDownload","security":[{"PbxServerAuth":[]}],"description":"Returns the sound file download identified by the path parameter. Multi-tenant scoping is\nenforced: the caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"audio\/mpeg"}},{"name":"soundFileId","in":"path","schema":{"type":"integer"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"localhost:8083"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:16:41 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"audio\/mpeg"}},"Content-Disposition":{"schema":{"type":"string","example":"attachment; filename=\"soundFile-1.mp3\""}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":58}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"audio\/mpeg":{"schema":{"type":"string","format":"binary","example":"soundFile-1.mp3"},"example":"soundFile-1.mp3"}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/layout":{"get":{"tags":["Users"],"summary":"Get the active Status Changer layout (user)","operationId":"getUserLayout","description":"Resolve and return the active Tempus Status Changer layout for the\nauthenticated user. The PBX is derived server-side from the bearer token\nand cannot be supplied by the client.\n\nResolution rules:\n\n- The user's PBX must be set on the token. If it is not, the request fails\n  with `400`.\n- The active layout (`is_active = true`) for the user's PBX is selected. If\n  the user belongs to a group and an active layout targets that group, the\n  most recently created group-targeted layout wins; otherwise the first\n  active layout for the PBX is returned.\n- If no active layout exists for the PBX, the request fails with `404`.\n\nThe response is returned in the legacy `tempus` representation, wrapped in a\n`data` envelope, and includes a `filters` echo of any `filter` query values.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"options":{"type":"object","description":"Client behaviour options for the layout.","properties":{"geoEnable":{"type":"boolean"},"geoForce":{"type":"boolean"},"postAction":{"type":"boolean"},"updateTimer":{"type":"integer","description":"Status refresh interval in milliseconds."}}},"layout":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mxvp_user_id":{"type":"string","format":"uuid","description":"The PBX identifier the layout belongs to."},"name":{"type":"string"},"displayflags":{"type":"string"},"type":{"type":"string"},"delete_date":{"type":["string","null"]},"tl_layouts_statuses":{"type":"array","description":"The statuses placed on the layout grid, in the legacy\nTempus shape.\n","items":{"type":"object","properties":{"tllayout_id":{"type":"string","format":"uuid"},"status_id":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mxvp_user_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"icon":{"type":["string","null"]},"fontcolor":{"type":"string"},"backgroundcolor":{"type":"string"},"css":{"type":"string"},"comment":{"type":"string"},"payable":{"type":"boolean"},"action":{"type":["string","null"]},"migration_id":{"type":["string","null"]},"mapping_id":{"type":"integer"},"delete_date":{"type":["string","null"]},"sub_status_layouts":{"type":"array","items":{"type":"object"}},"meta_data":{"type":"object"},"allow_multiselect":{"type":"boolean"},"sub_status_selection_mandatory":{"type":"boolean"},"sub_statuses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object"}}}}}},"position":{"type":"integer"},"size":{"type":"integer"},"toggle_status_id":{"type":["string","null"]}}}}}},"preview_url":{"type":"string","format":"uri","description":"Absolute URL to a preview render of the layout."}}},"filters":{"type":"object","description":"Echo of any `filter` query parameters supplied."}}},"example":{"data":{"options":{"geoEnable":true,"geoForce":false,"postAction":false,"updateTimer":5000},"layout":{"id":"550e8400-e29b-41d4-a716-446655440000","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440001","name":"Customer Support","displayflags":"DWML","type":"default","delete_date":null,"tl_layouts_statuses":[{"tllayout_id":"550e8400-e29b-41d4-a716-446655440000","status_id":{"id":"550e8400-e29b-41d4-a716-446655440010","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440001","name":"Working","icon":"briefcase","fontcolor":"#FFFFFF","backgroundcolor":"#1F8F4E","css":"","comment":"","payable":false,"action":null,"migration_id":null,"mapping_id":0,"delete_date":null,"sub_status_layouts":[],"meta_data":[],"allow_multiselect":false,"sub_status_selection_mandatory":false,"sub_statuses":[{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Customer Support","description":"Handling inbound support calls","style":{"icon_class":"headset"}}]},"position":0,"size":3,"toggle_status_id":null}]},"preview_url":"https:\/\/cockpit.voxbi.com\/layout-preview\/550e8400-e29b-41d4-a716-446655440000"},"filters":[]}}}},"400":{"description":"The authenticated user has no PBX associated with their token, so no\nlayout can be resolved.\n"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/statuses":{"get":{"tags":["Statuses"],"summary":"List statuse","operationId":"listStatuses","description":"Returns a paginated list of statuses. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, pbx_id, mxvp_id, name, icon, font_color, background_color, css, comment, paid, action and sync_tempus.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Tempus presence status: a top-level value (for example Available, Lunch,\nMeeting) that a user can broadcast. Visual styling is carried inside the\n`style` JSON object and behavioural switches inside `meta_data.flags`.\n\nThis schema documents the default response shape returned by the status\nendpoints. The API can also emit a legacy \"tempus\" representation (selected\nby a format parameter) whose field names differ (`mxvp_user_id`, `icon`,\n`fontcolor`, `backgroundcolor`, `comment`, and similar). Integrators should\ntarget the default shape described here.\n\nThe `sub_statuses` array is only populated when the `subStatuses` relation is\neager loaded by the request; otherwise it is returned as an empty array.\n","required":["id","name","description","style","availability","meta_data","allow_multiselect","sub_status_selection_mandatory","sub_statuses","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique status identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"name":{"type":"string","maxLength":255,"description":"Human-readable name of the status as shown to users.","example":"Working"},"description":{"type":["string","null"],"description":"Optional free-form description of what the status represents.","example":"Standard work activity"},"style":{"type":["object","null"],"description":"Visual styling for the status pill (icon and colours). Null when no\nstyling has been configured.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier rendered with the status (for example\nbriefcase, coffee, headset).\n","example":"briefcase"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text of the status pill.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the background of the status pill.","example":"#1F8F4E"}}},"availability":{"type":["string","null"],"description":"Roll-up availability category exposed to telephony and presence features.\nNull when the status has no mapped availability.\n","enum":["available","unavailable","busy","meeting","away"],"example":"available"},"meta_data":{"type":["object","null"],"description":"Extended behavioural settings. The `flags` array carries opt-in switches\nthat drive status behaviour, such as `payable`, `pbx_reachable`,\n`do_not_disturb`, `chat_available`, `temp_break`, `calculate_lunch_time`,\n`pbx_not_reachable`, and `auto_stop_target`. Additional implementation\nkeys may also be present.\n","properties":{"flags":{"type":"array","description":"Behavioural flags currently enabled on this status.","items":{"type":"string","enum":["calculate_lunch_time","pbx_reachable","payable","do_not_disturb","chat_available","temp_break","pbx_not_reachable","auto_stop_target"]},"example":["pbx_reachable","payable"]}}},"allow_multiselect":{"type":"boolean","description":"Whether more than one sub-status can be selected at once while in this\nstatus. Defaults to false.\n","example":false},"sub_status_selection_mandatory":{"type":"boolean","description":"Whether the user must pick a sub-status when entering this status.\nDefaults to false.\n","example":false},"sub_statuses":{"type":"array","description":"Sub-statuses attached to this status. Only populated when the\n`subStatuses` relation is eager loaded by the request; otherwise returned\nas an empty array.\n","items":{"type":"object","required":["id","name","description","style"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","description":"Human-readable name of the sub-status.","example":"Customer Support"},"description":{"type":["string","null"],"description":"Optional free-form description of the sub-status.","example":"Handling inbound support calls"},"style":{"type":["object","null"],"description":"Visual styling for the sub-status, mirroring the parent status\n`style` object (icon and colours). Null when not configured.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier for the sub-status.","example":"headset"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the background.","example":"#2D6CDF"}}}}}},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the status was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the status was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","parent_id":"550e8400-e29b-41d4-a716-446655440000","name":"Working","description":"Standard work activity","style":{"icon_class":"briefcase","font_color":"#FFFFFF","bg_color":"#1F8F4E"},"availability":"available","meta_data":{"flags":["pbx_reachable","payable"]},"payable":true,"allow_multiselect":false,"sub_status_selection_mandatory":false,"sub_statuses_enabled":true,"ring_users_despite_right_to_disconnect":false,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/statuses\/{id}":{"get":{"tags":["Statuses"],"summary":"Get a Statu","operationId":"getStatus","description":"Returns the status identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Tempus presence status: a top-level value (for example Available, Lunch,\nMeeting) that a user can broadcast. Visual styling is carried inside the\n`style` JSON object and behavioural switches inside `meta_data.flags`.\n\nThis schema documents the default response shape returned by the status\nendpoints. The API can also emit a legacy \"tempus\" representation (selected\nby a format parameter) whose field names differ (`mxvp_user_id`, `icon`,\n`fontcolor`, `backgroundcolor`, `comment`, and similar). Integrators should\ntarget the default shape described here.\n\nThe `sub_statuses` array is only populated when the `subStatuses` relation is\neager loaded by the request; otherwise it is returned as an empty array.\n","required":["id","name","description","style","availability","meta_data","allow_multiselect","sub_status_selection_mandatory","sub_statuses","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique status identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"name":{"type":"string","maxLength":255,"description":"Human-readable name of the status as shown to users.","example":"Working"},"description":{"type":["string","null"],"description":"Optional free-form description of what the status represents.","example":"Standard work activity"},"style":{"type":["object","null"],"description":"Visual styling for the status pill (icon and colours). Null when no\nstyling has been configured.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier rendered with the status (for example\nbriefcase, coffee, headset).\n","example":"briefcase"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text of the status pill.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the background of the status pill.","example":"#1F8F4E"}}},"availability":{"type":["string","null"],"description":"Roll-up availability category exposed to telephony and presence features.\nNull when the status has no mapped availability.\n","enum":["available","unavailable","busy","meeting","away"],"example":"available"},"meta_data":{"type":["object","null"],"description":"Extended behavioural settings. The `flags` array carries opt-in switches\nthat drive status behaviour, such as `payable`, `pbx_reachable`,\n`do_not_disturb`, `chat_available`, `temp_break`, `calculate_lunch_time`,\n`pbx_not_reachable`, and `auto_stop_target`. Additional implementation\nkeys may also be present.\n","properties":{"flags":{"type":"array","description":"Behavioural flags currently enabled on this status.","items":{"type":"string","enum":["calculate_lunch_time","pbx_reachable","payable","do_not_disturb","chat_available","temp_break","pbx_not_reachable","auto_stop_target"]},"example":["pbx_reachable","payable"]}}},"allow_multiselect":{"type":"boolean","description":"Whether more than one sub-status can be selected at once while in this\nstatus. Defaults to false.\n","example":false},"sub_status_selection_mandatory":{"type":"boolean","description":"Whether the user must pick a sub-status when entering this status.\nDefaults to false.\n","example":false},"sub_statuses":{"type":"array","description":"Sub-statuses attached to this status. Only populated when the\n`subStatuses` relation is eager loaded by the request; otherwise returned\nas an empty array.\n","items":{"type":"object","required":["id","name","description","style"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the sub-status.","example":"550e8400-e29b-41d4-a716-446655440010"},"name":{"type":"string","description":"Human-readable name of the sub-status.","example":"Customer Support"},"description":{"type":["string","null"],"description":"Optional free-form description of the sub-status.","example":"Handling inbound support calls"},"style":{"type":["object","null"],"description":"Visual styling for the sub-status, mirroring the parent status\n`style` object (icon and colours). Null when not configured.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier for the sub-status.","example":"headset"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the background.","example":"#2D6CDF"}}}}}},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the status was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the status was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","parent_id":"550e8400-e29b-41d4-a716-446655440000","name":"Working","description":"Standard work activity","style":{"icon_class":"briefcase","font_color":"#FFFFFF","bg_color":"#1F8F4E"},"availability":"available","meta_data":{"flags":["pbx_reachable","payable"]},"payable":true,"allow_multiselect":false,"sub_status_selection_mandatory":false,"sub_statuses_enabled":true,"ring_users_despite_right_to_disconnect":false,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/sub-statuses":{"get":{"tags":["Substatuses"],"summary":"List substatuse","operationId":"listSubStatuses","description":"Returns a paginated list of sub statuses. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"The filter key can be any of the following keys: id, pbx_id, mxvp_user_id, name, icon, font_color, background_color, css, comment, action and sync_tempus.\n\nThe filter value can be any string or number.\n\nYou can also apply multiple filters using `filter[key1]=value1&filter[key2]=value2`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Tempus sub-status: a refinement of a parent status (for example \"Lunch\" under\nthe \"Away\" status). Sub-statuses let a status be broken down into more specific\nactivity reasons. Visual styling (icon and colours) is held inside the `style`\nJSON object.\n\nThe `usage` array is only present when the related parent statuses have been\neager-loaded (typically on a single-resource or detail response). When statuses\nare not loaded it is returned as an empty array. Each `usage` entry describes a\nparent `TempusStatus` that references this sub-status, together with the pivot\nflags that govern how the sub-status behaves under that parent.\n","required":["id","name","usage"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique sub-status identifier.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"name":{"type":"string","maxLength":50,"description":"Display name of the sub-status shown to agents and in reports.","example":"Lunch"},"description":{"type":["string","null"],"description":"Optional free-form description explaining the purpose of the sub-status.","example":"Midday lunch break"},"style":{"type":["object","null"],"description":"Visual styling for the sub-status. Drives the icon and colours used when\nthe sub-status is rendered as a pill or badge. Null when no styling is set.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier used for the sub-status. One of the\nicon set allowed by the platform (for example \"utensils\", \"coffee\",\n\"headset\", \"car\", \"home\").\n","example":"utensils"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text or icon.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the sub-status pill background.","example":"#E5A100"}}},"usage":{"type":"array","description":"Parent statuses that reference this sub-status, exposed only when the\n`statuses` relationship is eager-loaded; otherwise returned as an empty\narray. Each entry is a parent `TempusStatus` enriched with the pivot\nconfiguration that controls how the sub-status behaves under that parent.\n","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the parent status.","example":"550e8400-e29b-41d4-a716-446655440010","readOnly":true},"parent_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the status this parent status is itself nested under,\nwhen statuses form a hierarchy. Null for a top-level status.\n","example":"550e8400-e29b-41d4-a716-446655440011"},"name":{"type":"string","description":"Display name of the parent status.","example":"Away"},"description":{"type":["string","null"],"description":"Optional free-form description of the parent status.","example":"Agent is away from the desk"},"style":{"type":["object","null"],"description":"Visual styling for the parent status (icon and colours), mirroring\nthe structure of the sub-status `style` object. Null when unset.\n","properties":{"icon_class":{"type":["string","null"],"description":"Font Awesome icon identifier for the parent status.","example":"pause"},"font_color":{"type":["string","null"],"description":"Hex colour used for the foreground text or icon.","example":"#FFFFFF"},"bg_color":{"type":["string","null"],"description":"Hex colour used as the parent status pill background.","example":"#6C757D"}}},"availability":{"type":["string","null"],"description":"Availability behaviour the parent status maps to (for example whether\nan agent in this status is considered available, away, or offline).\nNull when not configured.\n","example":"away"},"meta_data":{"type":["object","null"],"description":"Extended settings for the parent status, such as feature flags.\nReturned as a free-form JSON object.\n","additionalProperties":true,"example":{"flags":["billable"]}},"allow_multiselect":{"type":"boolean","description":"Whether multiple sub-statuses may be selected at once under this\nparent status. Defaults to false when not set on the pivot.\n","example":false},"sub_status_selection_mandatory":{"type":"boolean","description":"Whether selecting a sub-status is mandatory when an agent enters this\nparent status. Defaults to false when not set on the pivot.\n","example":false},"payable":{"type":"boolean","description":"Whether time recorded under this parent status counts as payable\nworking time. Defaults to false when not set on the pivot.\n","example":true},"mapping_id":{"type":["string","null"],"description":"Optional external mapping identifier used to align this status with a\ncode in an integrated payroll or time-tracking system. Null when no\nmapping is configured.\n","example":"PAYROLL-LUNCH-01"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the parent status was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the parent status was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the sub-status was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the sub-status was last updated.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","name":"Lunch","description":"Lunch break","style":{"icon_class":"utensils","font_color":"#FFFFFF","bg_color":"#E5A100"},"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z","deleted_at":"2024-03-01T08:29:07Z"}],"links":{"first":"http:\/\/localhost\/api\/v1\/resources?page=1","last":"http:\/\/localhost\/api\/v1\/resources?page=1"},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"http:\/\/localhost\/api\/v1\/resources?page=1","label":"first","active":true}],"path":"http:\/\/localhost\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/tags":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Tags"],"summary":"List tag","operationId":"listTags","description":"Returns a paginated list of tags. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `name`, `description`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["Tags"],"summary":"Create a tag","operationId":"createTag","description":"Create a new tag and optionally attach it to a set of users and SIP devices.\nThe `pbx_id` is forced from the authenticated user and must not be sent in\nthe request body.\n","security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["pbx_id","name"],"properties":{"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant). Must match the authenticated user's PBX."},"name":{"type":"string","minLength":3,"maxLength":64,"description":"Tag name (must be unique within the PBX)"},"description":{"type":["string","null"],"minLength":3,"maxLength":255},"users":{"type":"array","description":"Identifiers of users to attach this tag to","items":{"type":"string","format":"uuid"}},"sipDevices":{"type":"array","description":"Identifiers of SIP devices to attach this tag to","items":{"type":"string","format":"uuid"}}}},"example":{"pbx_id":"550e8400-e29b-41d4-a716-446655440001","name":"VIP","description":"Customers with priority routing","users":["550e8400-e29b-41d4-a716-446655440010"],"sipDevices":["550e8400-e29b-41d4-a716-446655440020"]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/tags\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Tags"],"summary":"Get a Tag","operationId":"getTag","description":"Returns the tag identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/twinnings":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Twinning"],"summary":"List twinning","operationId":"listTwinnings","description":"Returns a paginated list of twinnings. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `status`, `type`, `phone_number`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/twinnings\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Twinning"],"summary":"Get a Twinning","operationId":"getTwinning","description":"Returns the twinning identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Users"],"summary":"List user","operationId":"listUsers","description":"Returns a paginated list of users. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","x-codeSamples":[{"lang":"curl","label":"cURL","source":"curl 'https:\/\/cockpit.voxbi.com\/api\/v1\/users?page=1&perPage=25' \\\n  -H 'Accept: application\/json' \\\n  -H 'Authorization: Bearer <YOUR_TOKEN>'\n"},{"lang":"JavaScript","label":"JavaScript (fetch)","source":"const res = await fetch('https:\/\/cockpit.voxbi.com\/api\/v1\/users?page=1&perPage=25', {\n  headers: {\n    'Accept': 'application\/json',\n    'Authorization': `Bearer ${token}`,\n  },\n});\nconst { data, meta, links } = await res.json();\n"},{"lang":"PHP","label":"PHP (Guzzle)","source":"$client = new GuzzleHttp\\Client();\n$response = $client->get('https:\/\/cockpit.voxbi.com\/api\/v1\/users', [\n    'headers' => [\n        'Accept' => 'application\/json',\n        'Authorization' => \"Bearer {$token}\",\n    ],\n    'query' => ['page' => 1, 'perPage' => 25, 'filter[status]' => 'active'],\n]);\n$users = json_decode($response->getBody(), true)['data'];\n"}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"search","in":"query","required":false,"description":"Free-text search across the resource's searchable fields.","schema":{"type":"string"},"example":"whatever"},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","required":false,"description":"Field to sort by. Prefix with `-` for descending order (e.g. `-created_at`).\n","schema":{"type":"string"},"example":"id"},{"name":"filter[key]","description":"Filter the list by one or more fields. Allowed keys: `first_name`, `last_name`, `email`, `status`, `vip`, `show_in_address_book`.\nApply several at once with filter[key1]=value1&filter[key2]=value2.\n","in":"query","required":false,"schema":{"type":"string"},"example":"whateverValue"},{"name":"include","description":"Comma-separated related resources to embed (dot-nested where\nshown). Allowed: `extensions`, `groups`, `allowManageGroupContacts`, `allowAccessToGroupContacts`, `sipDevices`, `twinnings`, `callerIdentities`, `locations`, `languages`, `tags`, `queues`.\n","in":"query","required":false,"schema":{"type":"string"},"example":"groups,callerIdentities"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"PBX user. Each user belongs to exactly one Pbx, owns optional extensions\nand devices, and carries a large set of feature flags controlling what they\ncan do in the Voxbi UI and on the telephony stack.\n\nSecrets and credentials are never exposed through the API. Relation keys are\nopt-in via `?include=`.\n","required":["id","pbx_id","first_name","email","status"],"properties":{"id":{"type":"string","format":"uuid","description":"User identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"first_name":{"type":"string","maxLength":64,"example":"Jane"},"last_name":{"type":["string","null"],"maxLength":64,"example":"Smith"},"name":{"type":"string","readOnly":true,"description":"Combined display name (accessor, respects PBX formatting settings)","example":"Jane Smith"},"full_name_with_email":{"type":"string","readOnly":true,"description":"Convenience label combining the display name and email","example":"Jane Smith <jane.smith@example.com>"},"email":{"type":"string","format":"email","maxLength":100,"example":"jane.smith@example.com"},"status":{"type":"string","enum":["enabled","disabled"],"example":"enabled"},"type":{"type":"string","description":"User category","enum":["user","pickup_line"],"example":"user"},"language":{"type":"string","description":"Preferred UI language","enum":["en","de","fr"],"example":"en"},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import","microsoft_entra"],"example":"manual"},"vip":{"type":"boolean","description":"Whether the user is flagged as VIP","example":false},"show_in_address_book":{"type":"boolean","description":"Whether the user appears in the shared address book","example":true},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default outbound CID for this user","example":"550e8400-e29b-41d4-a716-446655440004"},"caller_identity_internal_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the internal caller ID","example":"550e8400-e29b-41d4-a716-446655440002"},"caller_identity_external_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the external caller ID","example":"550e8400-e29b-41d4-a716-446655440003"},"allow_telephony":{"type":"boolean","description":"Whether the user can place and receive calls","example":true},"allow_call_forwarding":{"type":"boolean","example":true},"allow_change_twinning_dest":{"type":"boolean","description":"Whether the user may change their twinning destination","example":true},"allow_dnd":{"type":"boolean","description":"Whether the user may set their own Do Not Disturb","example":true},"allow_status_changer":{"type":"boolean","description":"Whether the user may change other users' statuses","example":false},"allow_anonymous_calls":{"type":"boolean","description":"Whether the user is allowed to place anonymous outbound calls","example":false},"allow_international_calls":{"type":"boolean","example":false},"allow_eu_calls":{"type":"boolean","example":true},"allow_national_calls":{"type":"boolean","example":true},"allow_premium_numbers":{"type":"boolean","example":false},"allow_sms":{"type":"boolean","example":false},"allow_manage_global_contacts":{"type":"boolean","example":false},"allow_manage_voicemail_parameters":{"type":"boolean","example":true},"allow_in_call_recording":{"type":"boolean","description":"Whether the user can start\/stop recording during a call","example":false},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable by this user","example":true},"allow_grafana_access":{"type":"boolean","description":"Whether the user can access the Grafana dashboards","example":false},"allow_right_to_disconnect":{"type":"boolean","description":"Whether the user may set their own right-to-disconnect schedule","example":true},"right_to_disconnect":{"type":"boolean","description":"Whether the right-to-disconnect rule is currently enforced","example":false},"concurrent_calls":{"type":"boolean","description":"Whether the user may have multiple simultaneous calls","example":true},"extension_roaming":{"type":"boolean","description":"Whether the user may hot-desk by logging into other devices","example":true},"record_your_calls":{"type":"boolean","description":"Default per-call recording flag for outbound external calls","example":false},"record_your_internal_calls":{"type":"integer","description":"Tri-state flag controlling internal-call recording (0 = off, 1 = on,\n2 = follow PBX default). Stored as an integer despite the boolean-style\nname.\n","example":2},"access_all_call_recordings":{"type":"boolean","description":"Whether the user may access call recordings of others","example":false},"call_recordings_visibility":{"type":"string","enum":["all_calls","own_calls_only"],"example":"own_calls_only"},"call_information_visibility":{"type":"string","enum":["none","own_calls","own_group_only"],"example":"own_calls"},"send_missed_call_via_email":{"type":"boolean","example":true},"limit_email_missed_call_to_direct":{"type":"boolean","description":"Whether missed-call emails are limited to directly-dialled calls","example":false},"show_caller_id_for_twinning_call":{"type":"integer","description":"Tri-state flag controlling caller-ID display on twinning calls (0 = off,\n1 = on, 2 = follow PBX default).\n","example":2},"voicemail_type":{"type":"string","description":"Voicemail mode","enum":["disabled","enabled","internal","external"],"example":"internal"},"voicemail_destination":{"type":"string","description":"Where voicemail notifications are sent","enum":["email_only","email_and_phone"],"example":"email_only"},"invited_at":{"type":["string","null"],"format":"date-time","description":"When the user was invited (if onboarding via invitation)","example":null},"accepted_invitation_at":{"type":["string","null"],"format":"date-time","description":"When the user accepted their invitation","example":null},"email_verified_at":{"type":["string","null"],"format":"date-time","example":"2024-02-15T10:00:00Z","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"extensions":{"type":"array","description":"Extensions owned by the user. Returned only when requested via `?include=extensions`.","items":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"groups":{"type":"array","description":"Groups the user belongs to. Returned only when requested via `?include=groups`.","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_manage_group_contacts":{"type":"array","description":"Groups whose contacts the user may manage. Returned only when requested\nvia `?include=allowManageGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_access_to_group_contacts":{"type":"array","description":"Groups whose contacts the user may access. Returned only when requested\nvia `?include=allowAccessToGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"sip_devices":{"type":"array","description":"SIP devices assigned to the user. Returned only when requested via `?include=sipDevices`.","items":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}},"twinnings":{"type":"array","description":"Twinnings configured for the user. Returned only when requested via `?include=twinnings`.","items":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Effective (inherited) caller identities for the user: own plus those of\nthe user's groups plus the PBX's. Returned only when requested via\n`?include=callerIdentities`.\n","items":{"type":"object"}},"locations":{"type":"array","description":"Locations the user is associated with. Returned only when requested via `?include=locations`.","items":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"languages":{"type":"array","description":"Languages the user is associated with. Returned only when requested via `?include=languages`.","items":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"tags":{"type":"array","description":"Tags attached to the user. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"queues":{"type":"array","description":"Queues the user is a member of. Returned only when requested via `?include=queues`.","items":{"type":"object"}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{id}":{"get":{"security":[{"bearerAuth":[]},{"IntegrationApiKey":[]}],"tags":["Users"],"summary":"Get an User","operationId":"getUser","description":"Returns the user identified by the path parameter. Multi-tenant scoping is enforced: the\ncaller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"PBX user. Each user belongs to exactly one Pbx, owns optional extensions\nand devices, and carries a large set of feature flags controlling what they\ncan do in the Voxbi UI and on the telephony stack.\n\nSecrets and credentials are never exposed through the API. Relation keys are\nopt-in via `?include=`.\n","required":["id","pbx_id","first_name","email","status"],"properties":{"id":{"type":"string","format":"uuid","description":"User identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"first_name":{"type":"string","maxLength":64,"example":"Jane"},"last_name":{"type":["string","null"],"maxLength":64,"example":"Smith"},"name":{"type":"string","readOnly":true,"description":"Combined display name (accessor, respects PBX formatting settings)","example":"Jane Smith"},"full_name_with_email":{"type":"string","readOnly":true,"description":"Convenience label combining the display name and email","example":"Jane Smith <jane.smith@example.com>"},"email":{"type":"string","format":"email","maxLength":100,"example":"jane.smith@example.com"},"status":{"type":"string","enum":["enabled","disabled"],"example":"enabled"},"type":{"type":"string","description":"User category","enum":["user","pickup_line"],"example":"user"},"language":{"type":"string","description":"Preferred UI language","enum":["en","de","fr"],"example":"en"},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import","microsoft_entra"],"example":"manual"},"vip":{"type":"boolean","description":"Whether the user is flagged as VIP","example":false},"show_in_address_book":{"type":"boolean","description":"Whether the user appears in the shared address book","example":true},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default outbound CID for this user","example":"550e8400-e29b-41d4-a716-446655440004"},"caller_identity_internal_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the internal caller ID","example":"550e8400-e29b-41d4-a716-446655440002"},"caller_identity_external_extension_id":{"type":["string","null"],"format":"uuid","description":"Extension shown as the external caller ID","example":"550e8400-e29b-41d4-a716-446655440003"},"allow_telephony":{"type":"boolean","description":"Whether the user can place and receive calls","example":true},"allow_call_forwarding":{"type":"boolean","example":true},"allow_change_twinning_dest":{"type":"boolean","description":"Whether the user may change their twinning destination","example":true},"allow_dnd":{"type":"boolean","description":"Whether the user may set their own Do Not Disturb","example":true},"allow_status_changer":{"type":"boolean","description":"Whether the user may change other users' statuses","example":false},"allow_anonymous_calls":{"type":"boolean","description":"Whether the user is allowed to place anonymous outbound calls","example":false},"allow_international_calls":{"type":"boolean","example":false},"allow_eu_calls":{"type":"boolean","example":true},"allow_national_calls":{"type":"boolean","example":true},"allow_premium_numbers":{"type":"boolean","example":false},"allow_sms":{"type":"boolean","example":false},"allow_manage_global_contacts":{"type":"boolean","example":false},"allow_manage_voicemail_parameters":{"type":"boolean","example":true},"allow_in_call_recording":{"type":"boolean","description":"Whether the user can start\/stop recording during a call","example":false},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable by this user","example":true},"allow_grafana_access":{"type":"boolean","description":"Whether the user can access the Grafana dashboards","example":false},"allow_right_to_disconnect":{"type":"boolean","description":"Whether the user may set their own right-to-disconnect schedule","example":true},"right_to_disconnect":{"type":"boolean","description":"Whether the right-to-disconnect rule is currently enforced","example":false},"concurrent_calls":{"type":"boolean","description":"Whether the user may have multiple simultaneous calls","example":true},"extension_roaming":{"type":"boolean","description":"Whether the user may hot-desk by logging into other devices","example":true},"record_your_calls":{"type":"boolean","description":"Default per-call recording flag for outbound external calls","example":false},"record_your_internal_calls":{"type":"integer","description":"Tri-state flag controlling internal-call recording (0 = off, 1 = on,\n2 = follow PBX default). Stored as an integer despite the boolean-style\nname.\n","example":2},"access_all_call_recordings":{"type":"boolean","description":"Whether the user may access call recordings of others","example":false},"call_recordings_visibility":{"type":"string","enum":["all_calls","own_calls_only"],"example":"own_calls_only"},"call_information_visibility":{"type":"string","enum":["none","own_calls","own_group_only"],"example":"own_calls"},"send_missed_call_via_email":{"type":"boolean","example":true},"limit_email_missed_call_to_direct":{"type":"boolean","description":"Whether missed-call emails are limited to directly-dialled calls","example":false},"show_caller_id_for_twinning_call":{"type":"integer","description":"Tri-state flag controlling caller-ID display on twinning calls (0 = off,\n1 = on, 2 = follow PBX default).\n","example":2},"voicemail_type":{"type":"string","description":"Voicemail mode","enum":["disabled","enabled","internal","external"],"example":"internal"},"voicemail_destination":{"type":"string","description":"Where voicemail notifications are sent","enum":["email_only","email_and_phone"],"example":"email_only"},"invited_at":{"type":["string","null"],"format":"date-time","description":"When the user was invited (if onboarding via invitation)","example":null},"accepted_invitation_at":{"type":["string","null"],"format":"date-time","description":"When the user accepted their invitation","example":null},"email_verified_at":{"type":["string","null"],"format":"date-time","example":"2024-02-15T10:00:00Z","readOnly":true},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"extensions":{"type":"array","description":"Extensions owned by the user. Returned only when requested via `?include=extensions`.","items":{"type":"object","description":"Internal dial number assigned to a user, device, queue, or other PBX entity.\nPer-direction call recording is controlled by the two `record_*_calls` flags.\nThe assignment is exposed as a friendly `assigned_to_type` + `assigned_to_id`\n(always present); the full `assigned_to` object is opt-in.\n","required":["id","pbx_id","number"],"properties":{"id":{"type":"string","format":"uuid","description":"Extension identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"assigned_to_type":{"type":["string","null"],"description":"Friendly type of the entity this extension is assigned to","enum":["user","sip_device","famulor_agent"],"example":"user"},"assigned_to_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the entity this extension is assigned to","example":"550e8400-e29b-41d4-a716-446655440002"},"external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to external inbound calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440003"},"internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow applied to internal calls hitting this extension","example":"550e8400-e29b-41d4-a716-446655440004"},"number":{"type":"string","maxLength":16,"description":"Dialable extension digits","example":"1337"},"name":{"type":["string","null"],"description":"Display name for the extension","example":"Support line"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-line support line"},"record_external_calls":{"type":"boolean","description":"Whether external calls on this extension are recorded","example":true},"record_internal_calls":{"type":"boolean","description":"Whether internal calls on this extension are recorded","example":false},"sync_source":{"type":"string","description":"Provisioning origin (cast to ExtensionSyncSource)","enum":["manual","provision","legacy_import"],"example":"manual"},"full_name_with_extension_number":{"type":["string","null"],"description":"Convenience label combining the assignee's name and the extension number","example":"Jane Smith (1337)","readOnly":true},"assigned_to":{"type":"object","description":"The resolved owner of this extension; shape varies by `assigned_to_type`.\nReturned only when requested via `?include=user` (or `?include=sipDevice`\n\/ `?include=famulorAgent`).\n"},"employee_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the employee record linked to the assigned user.\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the assigned user's employee, taken from their currently\nactive contract (null when the employee has no active contract).\nReturned only when requested via `?include=user.employee`.\n","example":"550e8400-e29b-41d4-a716-446655440006"},"is_favorite":{"type":"boolean","description":"Whether the extension's user is one of the **calling user's** favourites.\nPRINCIPAL-CONDITIONAL: returned only for user-owned (Bearer) tokens and\nOMITTED entirely for PBX API-key tokens (a PBX has no per-user favourites).\n","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"groups":{"type":"array","description":"Groups the user belongs to. Returned only when requested via `?include=groups`.","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_manage_group_contacts":{"type":"array","description":"Groups whose contacts the user may manage. Returned only when requested\nvia `?include=allowManageGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"allow_access_to_group_contacts":{"type":"array","description":"Groups whose contacts the user may access. Returned only when requested\nvia `?include=allowAccessToGroupContacts`.\n","items":{"type":"object","description":"Group of users that share routing defaults and (optionally) a common caller\nidentity. Many fields are foreign keys pointing at defaults used when the\ngroup's users place or receive calls.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Group identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"default_internal_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for internal calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440002"},"default_external_call_flow_id":{"type":["string","null"],"format":"uuid","description":"Call flow used for external calls reaching this group","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_outside_the_group":{"type":["string","null"],"format":"uuid","description":"Extension displayed to non-group members","example":"550e8400-e29b-41d4-a716-446655440005"},"default_caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Default caller identity applied to the group's outbound calls","example":"550e8400-e29b-41d4-a716-446655440004"},"external_uid":{"type":["string","null"],"description":"External identifier from a CRM or directory sync","example":"grp-support"},"allow_call_pickups":{"type":"boolean","description":"Whether group members may pick up each others' ringing calls","example":true},"name":{"type":"string","maxLength":64,"example":"Support team"},"description":{"type":["string","null"],"maxLength":255,"example":"First-line support"},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the group's CIDs include the PBX-default outbound numbers","example":false},"display_tab_to_everyone_inside_voxbi":{"type":"boolean","description":"Whether the group's tab is shown to everyone in the PBX","example":false},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"users":{"type":"array","description":"Members of the group, each as a user reference. Returned only when\nrequested via `?include=users`.\n","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440006","readOnly":true},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Smith"},"email":{"type":["string","null"],"format":"email","example":"jane.smith@example.com"}}}}}}},"sip_devices":{"type":"array","description":"SIP devices assigned to the user. Returned only when requested via `?include=sipDevices`.","items":{"type":"object","description":"Physical or soft SIP endpoint (deskphone, softphone, ATA, trunk) registered\nagainst the PBX. The device owner is exposed as a friendly `target_type`\n(`user` \/ `extension`) plus `target_id`; the full `target` object is opt-in.\nThe SIP password is never exposed.\n","required":["id","pbx_id","name","is_enabled","type"],"properties":{"id":{"type":"string","format":"uuid","description":"SIP device identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"target_type":{"type":["string","null"],"description":"Friendly type of the entity the device is assigned to","enum":["user","extension"],"example":"user"},"target_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the target entity","example":"550e8400-e29b-41d4-a716-446655440003"},"extension_id_shown_for_internal_calls":{"type":["string","null"],"format":"uuid","description":"Extension displayed in the device's caller ID for internal calls","example":null},"roaming_user_id":{"type":["string","null"],"format":"uuid","description":"User currently roamed onto this device","example":null},"location_id":{"type":["string","null"],"format":"uuid","description":"Physical location the device is installed at","example":"550e8400-e29b-41d4-a716-446655440002"},"parent_sip_device_id":{"type":["string","null"],"format":"uuid","description":"Parent device (e.g. a Gigaset base) for handset child devices","example":null},"name":{"type":"string","maxLength":128,"example":"Reception desk phone"},"description":{"type":["string","null"],"maxLength":255,"example":"Front-desk Yealink T46U"},"is_enabled":{"type":"boolean","description":"Whether the device is currently enabled","example":true},"ip_internal":{"type":["string","null"],"description":"Last-seen internal IP","example":"192.168.1.42"},"ip_external":{"type":["string","null"],"description":"Last-seen external IP","example":"203.0.113.10"},"user_agent":{"type":["string","null"],"description":"SIP User-Agent string reported by the device","example":"Yealink SIP-T46U 108.86.0.10"},"mac":{"type":["string","null"],"description":"MAC address","example":"00:0a:95:9d:68:16"},"vlan_phone":{"type":["integer","null"],"description":"VLAN id for the phone interface","example":100},"vlan_pc":{"type":["integer","null"],"description":"VLAN id for the PC pass-through interface","example":200},"sip_username":{"type":["string","null"],"maxLength":24,"description":"SIP authentication username","example":"device_001"},"alt_username":{"type":["string","null"],"description":"Alternate SIP username (used for multi-line registrations)","example":null},"transport":{"type":"string","description":"SIP transport","enum":["udp","tcp","tls"],"example":"tls"},"type":{"type":"string","description":"Device provisioning category","enum":["auto","manual","gigaset","trunk"],"example":"auto"},"allow_roaming":{"type":"boolean","description":"Whether the device accepts roamed-in users","example":false},"language":{"type":"string","description":"Display language for the device","example":"en"},"easy_deploy":{"type":["string","null"],"format":"date-time","description":"Timestamp until which the device is in easy-deploy mode","example":null},"notify":{"type":["string","null"],"format":"date-time","description":"Timestamp at which a SIP NOTIFY was last requested","example":null},"allow_default_pbxes_outgoing_phone_numbers":{"type":"boolean","description":"Whether the PBX default outbound numbers are usable from this device","example":false},"sync_source":{"type":"string","description":"Provisioning origin","enum":["manual","provision","legacy_import"],"example":"provision"},"custom_provisioning":{"type":["string","null"],"description":"Custom provisioning template snippet","example":null},"last_seen":{"type":["string","null"],"format":"date-time","description":"Last time the device registered","example":"2024-03-01T08:29:07Z"},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"target":{"type":"object","description":"The resolved device owner (a user or an extension); shape varies by\n`target_type`. Returned only when requested via `?include=target`.\n"},"tags":{"type":"array","description":"Tags attached to this device. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Caller identities available to this device. Returned only when requested\nvia `?include=callerIdentities`.\n","items":{"type":"object"}},"location":{"description":"The resolved installation location. Returned only when requested via\n`?include=location`.\n","allOf":[{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}]}}}},"twinnings":{"type":"array","description":"Twinnings configured for the user. Returned only when requested via `?include=twinnings`.","items":{"type":"object","description":"Twinning: an external destination that rings alongside a user's extension\n(a mobile phone or a Microsoft Teams endpoint). When a call reaches the user,\nthe twinned destination rings in parallel so the call can be answered away\nfrom the desk phone. Tenant scoping is derived from the attached user; this\nresource has no direct `pbx_id` column of its own.\n","required":["id","user_id","status","phone_number","delay","sync_source","type","dial_strategy","fmc_enabled","backup_phone_number"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the twinning.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"user_id":{"type":"string","format":"uuid","description":"Identifier of the user this twinning belongs to. The user also determines the PBX tenant this twinning is scoped to.","example":"550e8400-e29b-41d4-a716-446655440001"},"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active. Only an enabled twinning rings alongside the user's extension.","example":"enabled"},"phone_number":{"type":["string","null"],"description":"The twinned destination phone number, stored in E.164 format. Null when the twinning targets a Teams endpoint or has no number configured.","example":"+12125550100"},"delay":{"type":"integer","format":"int32","minimum":0,"description":"Number of seconds to wait after the call starts before the twinning leg begins ringing. A value of 0 means it rings immediately.","example":5},"sync_source":{"type":"string","enum":["manual","provision","legacy_import"],"description":"Origin of this twinning record. `manual` was created by a user, `provision` came from an automated provisioning step, and `legacy_import` was migrated from a previous system.","example":"manual"},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination, either a mobile phone or a Microsoft Teams endpoint.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed: `gsm_only` uses the cellular network only,\n`voip_only` uses the VoIP app only, and `voip_and_gsm_fallback` tries\nVoIP first and falls back to GSM. Only meaningful for mobile-type\ntwinnings that use the Fixed-Mobile Convergence (FMC) integration.\n","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence (FMC) is enabled for this twinning, allowing seamless handover between VoIP and the cellular network.","example":false},"backup_phone_number":{"type":["string","null"],"description":"Secondary phone number, in E.164 format, dialed when the primary FMC leg cannot be reached. Null when no backup is configured.","example":"+12125550101"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was created (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp when the twinning was last updated (ISO 8601, UTC).","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"caller_identities":{"type":"array","description":"Effective (inherited) caller identities for the user: own plus those of\nthe user's groups plus the PBX's. Returned only when requested via\n`?include=callerIdentities`.\n","items":{"type":"object"}},"locations":{"type":"array","description":"Locations the user is associated with. Returned only when requested via `?include=locations`.","items":{"type":"object","description":"Physical office or site associated with a PBX. Locations form a nested-set\ntree via `parent_id` + `lft`\/`rgt`\/`depth`. Street-level address fields are\nused for emergency call routing.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Location identifier","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Pbx identifier (tenant)","example":"550e8400-e29b-41d4-a716-446655440001"},"company_id":{"type":["string","null"],"format":"uuid","description":"Owning company identifier","example":"550e8400-e29b-41d4-a716-446655440004"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Parent location identifier in the nested-set tree","example":"550e8400-e29b-41d4-a716-446655440002"},"name":{"type":"string","maxLength":64,"example":"Luxembourg HQ"},"description":{"type":["string","null"],"maxLength":255,"example":"Main office, 5th floor"},"street_no":{"type":["string","null"],"description":"Street number portion of the address","example":"12"},"street":{"type":["string","null"],"example":"Main Street"},"city":{"type":["string","null"],"example":"Luxembourg"},"postal":{"type":["string","null"],"description":"Postal code","example":"1234"},"country_id":{"type":["string","null"],"format":"uuid","description":"Country identifier","example":"550e8400-e29b-41d4-a716-446655440003"},"lft":{"type":["integer","null"],"description":"Nested-set left bound","example":1},"rgt":{"type":["integer","null"],"description":"Nested-set right bound","example":10},"depth":{"type":["integer","null"],"description":"Tree depth (0 for root locations)","example":0},"enable_location_as_presence_status":{"type":"boolean","description":"Whether this location can be used as a presence status value","example":false},"style":{"type":["object","null"],"description":"Optional presentation style (badge icon and colours) for the location","example":{"icon_class":"la-map-pin","bg_color":"#3490dc","font_color":"#ffffff"}},"is_fixed_location":{"type":"boolean","description":"Whether this is a fixed (geofenced) physical location","example":true},"latitude":{"type":["number","null"],"format":"float","description":"Latitude of the location, in decimal degrees","example":49.6116},"longitude":{"type":["number","null"],"format":"float","description":"Longitude of the location, in decimal degrees","example":6.1319},"geofence_radius_m":{"type":["integer","null"],"description":"Geofence radius around the location, in metres","example":100},"created_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"languages":{"type":"array","description":"Languages the user is associated with. Returned only when requested via `?include=languages`.","items":{"type":"object","description":"A language defined for the tenant, used to label sound files, voice prompts\n(IVR announcements), and per-user language preferences. Each language belongs\nto exactly one Pbx (tenant) and is identified by a free-text name.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique language identifier (UUID).","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this language.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable language name as shown in the cockpit and selectors.","example":"English"},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was created. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the language was last updated. Null if not set.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"tags":{"type":"array","description":"Tags attached to the user. Returned only when requested via `?include=tags`.","items":{"type":"object","description":"Free-form label that can be attached to users, SIP devices, phone numbers, and\nother tenant resources for grouping, filtering, and reporting. Tags are scoped\nto a single Pbx (tenant). Associations to the resources a tag is applied to are\nheld on the relevant pivot tables, not on this schema.\n","required":["id","pbx_id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique tag identifier (UUID), assigned by the server on creation.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this tag. Tags are never shared across tenants.","example":"550e8400-e29b-41d4-a716-446655440001","readOnly":true},"name":{"type":"string","maxLength":64,"description":"Human-readable label for the tag, shown in dropdowns and used when filtering tagged resources.","example":"VIP Customers"},"description":{"type":["string","null"],"maxLength":255,"description":"Optional free-text note explaining the purpose of the tag. Null when no description was provided.","example":"Customers with priority routing and dedicated agents."},"created_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was created.","example":"2024-03-01T08:29:07Z","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp (ISO 8601, UTC) when the tag was last modified.","example":"2024-03-01T08:29:07Z","readOnly":true}}}},"queues":{"type":"array","description":"Queues the user is a member of. Returned only when requested via `?include=queues`.","items":{"type":"object"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{email}\/webrtc":{"get":{"tags":["Users"],"summary":"Get an user WebRTC configuration by Email","operationId":"getUserWebrtc","security":[{"ApiKeyAuth":[]}],"description":"Returns the user webrtc identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"email","in":"path","schema":{"type":"string"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"hostname":{"type":"string","example":"pbx.mixvoip.com"},"port":{"type":"integer","example":8089},"username":{"type":"string","example":"mixvoip_webrtc_1337"},"password":{"type":"string","example":"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"},"caller_identities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"root_phone_nuber_id":{"type":"integer","example":1},"external_caller_extension":{"type":"string","example":"1337"},"external_caller_number":{"type":"string","example":"2033331337"}}}},"allow_anonymous_calls":{"type":"boolean","example":true},"allow_call_forwarding":{"type":"boolean","example":true},"allow_change_twinning_dest":{"type":"boolean","example":true},"allow_dnd":{"type":"boolean","example":true},"allow_status_changer":{"type":"boolean","example":true},"call_information_visibility":{"type":"string","example":"own_calls","enum":["own_calls","own_group_only","none"]},"call_pickpup_restrictions":{"type":"string","example":"yes","enum":["yes","own_groups_only","no"]},"voicemail":{"type":"boolean","example":true},"voicemail_destination":{"type":"string","example":"email_only","enum":["email_only","email_and_phone"]},"voicemail_pin":{"type":"string","example":"1234"},"voicemail_type":{"type":"string","example":"enabled","enum":["enabled","external","internal"]}}},"example":{"hostname":"pbx.mixvoip.com","port":8089,"username":"mixvoip_webrtc_1337","password":"$2y$10$ePs3A38yC.ewAqS0CVLghuLvimTIm5Pf0HUw5155wM9wd16XVqpeS","caller_identities":[{"id":1,"root_phone_nuber_id":1,"external_caller_extension":"1337","external_caller_number":"2033331337"}],"allow_anonymous_calls":true,"allow_call_forwarding":true,"allow_change_twinning_dest":true,"allow_dnd":true,"allow_status_changer":true,"call_information_visibility":"own_calls","call_pickpup_restrictions":"yes","voicemail":true,"voicemail_destination":"email_only","voicemail_pin":"1234","voicemail_type":"enabled"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/qr-code":{"get":{"tags":["Users"],"summary":"Get QR code for authenticated user","operationId":"getUserQrCode","description":"Returns a paginated list of user qr code. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"qr_code":{"type":"string","description":"Base64-encoded QR code image","example":"data:image\/png;base64,iVBORw0KGgo="}}}}},"example":{"data":{"qr_code":"data:image\/png;base64,iVBORw0KGgo="}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/soop-status":{"get":{"tags":["Users"],"summary":"Get SOOP status for authenticated user","operationId":"getUserSoopStatus","description":"Returns a paginated list of user soop status. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","example":"online"},"sub_status":{"type":["string","null"],"example":"in_meeting"},"updated_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"}}}}},"example":{"data":{"status":"online","sub_status":null,"updated_at":"2023-10-17T14:12:22Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/favorites":{"post":{"tags":["Users"],"summary":"Toggle favorite user","operationId":"postUserFavorites","description":"Creates a new user favorites. Validation rules and required fields are defined in the\nrequest body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string","description":"UUID of the user to toggle as favorite","example":"550e8400-e29b-41d4-a716-446655440000"}}},"example":{"user_id":"550e8400-e29b-41d4-a716-446655440000"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"favorited":{"type":"boolean","description":"Whether the user is now a favorite (true) or was removed (false)","example":true}}}}},"example":{"data":{"favorited":true}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/poll":{"get":{"tags":["Users"],"summary":"Poll extensions with DND, status and in-call flags (user)","operationId":"getUserPoll","description":"Live board for every extension in the authenticated user's PBX whose extension is\nlinked to a user: current Tempus status, sub-statuses, DND, the in-call flag and,\nfor employees currently on leave, when they are next available.\n\nThe response is NOT a list and is NOT paginated: it is a single object keyed by\nCockpit user id, so a client can look a user up directly. Responses are cached per\nPBX for a few seconds, so a change made through another endpoint (for example\n`POST \/in-call`) surfaces here within that window rather than instantly.\n\n`in_call` is owned by Cockpit and comes from what the user's own client last reported\nto `POST \/in-call`. It is independent of whether the user has a running Tempus\ntimepoint, and a `true` decays to `false` after an hour if the hang-up is never\nreported. `updated_at` is the status\/timepoint change time, which is a different\nthing from `in_call_updated_at`.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","description":"Map of Cockpit user id to that user's live board entry.","additionalProperties":{"type":"object","properties":{"cockpit_user_id":{"type":"string","format":"uuid","description":"The Cockpit user the extension belongs to."},"cockpit_status_id":{"type":["string","null"],"format":"uuid","description":"Current Tempus status id in Cockpit."},"cockpit_status":{"type":["string","null"],"description":"Current Tempus status name."},"sub_statuses":{"type":"array","description":"Sub-statuses attached to the current status.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}},"number":{"type":"string","description":"Extension number."},"extintenabled":{"type":"boolean","description":"Always true; kept for backwards compatibility."},"status_id":{"type":["string","integer","null"],"description":"Phone-system status mapping id, falling back to the Cockpit status id."},"substatus_id":{"type":["string","null"],"description":"Reserved; always null."},"user_id":{"type":"string","format":"uuid","description":"Deprecated alias of `pbx_id`. Use `pbx_id`."},"pbx_id":{"type":"string","format":"uuid","description":"The PBX the extension belongs to."},"payable":{"type":"boolean","description":"Whether the current status counts as paid time."},"in_call":{"type":"boolean","description":"Whether the user is on a call right now, as last reported by their client\nthrough `POST \/in-call`. Expires back to false after an hour.\n"},"in_call_updated_at":{"type":["string","null"],"format":"date-time","description":"When `in_call` was last reported, null when nothing is reported."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When the current status last changed. Unrelated to `in_call_updated_at`."},"dnd":{"oneOf":[{"type":"boolean"},{"type":"array","items":{"type":"object"}}],"description":"false when the user has no DND rows, otherwise their DND settings."},"id":{"type":["string","integer","null"],"description":"Phone-system extension-status row id, when the status came from there."},"location_id":{"type":["string","null"],"format":"uuid","description":"Location on the user's latest timepoint."},"next_availability":{"type":["object","null"],"description":"Set only for active-contract employees who are unavailable right now because\nof an absence: when they are back, plus a ready-to-display message.\n","properties":{"next_available_date":{"type":"string","format":"date"},"next_available_at":{"type":["string","null"],"format":"date-time"},"message":{"type":"string"},"reason":{"type":["string","null"]},"absence":{"type":["object","null"]},"absence_window":{"type":["object","null"]}}}}}},"example":{"550e8400-e29b-41d4-a716-446655440000":{"cockpit_user_id":"550e8400-e29b-41d4-a716-446655440000","cockpit_status_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","cockpit_status":"Working","sub_statuses":[{"id":"6ba7b811-9dad-11d1-80b4-00c04fd430c8","name":"Office"}],"number":"101","extintenabled":true,"status_id":3,"substatus_id":null,"user_id":"6ba7b812-9dad-11d1-80b4-00c04fd430c8","pbx_id":"6ba7b812-9dad-11d1-80b4-00c04fd430c8","payable":true,"in_call":true,"in_call_updated_at":"2026-08-03T09:14:22+00:00","updated_at":"2026-08-03T08:00:00+00:00","dnd":false,"id":null,"location_id":null,"next_availability":null}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/in-call":{"get":{"tags":["Users"],"summary":"Read the authenticated user's in-call flag (user)","operationId":"getUserInCall","description":"Returns whether the authenticated user is currently reported as being on a call,\nplus when that was last reported. The flag is owned by Cockpit: it is whatever the\nclient last sent to `POST \/in-call`.\n\nA flag set to `true` is trusted for a limited window only (`ttl_seconds`, one hour by\ndefault). Past that window it decays back to `false` on its own, so a client that\nnever gets to report the hang-up (crash, network loss, killed app) cannot leave the\nuser marked in-call forever. `in_call_updated_at` and `expires_at` are `null` when\nnothing has been reported inside the window.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/InCallState"}}},"example":{"data":{"user_id":"550e8400-e29b-41d4-a716-446655440000","in_call":true,"in_call_updated_at":"2026-08-03T09:14:22+00:00","expires_at":"2026-08-03T10:14:22+00:00","ttl_seconds":3600}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}}}},"post":{"tags":["Users"],"summary":"Set the authenticated user's in-call flag (user)","operationId":"postUserInCall","description":"Reports whether the authenticated user is on a call right now: send `true` when the\ncall starts and `false` when it ends. The user is always taken from the bearer token,\nso this endpoint can never change anyone else's flag.\n\nThe call is idempotent: sending the same value again simply refreshes the timestamp\nand pushes the expiry window out. Sending `false` clears the flag immediately, and a\n`true` that is never cleared expires by itself after `ttl_seconds` (one hour by\ndefault), so it is safe to miss a hang-up report.\n\nThe new value is served by `GET \/poll` (as `in_call` and `in_call_updated_at`) within\nthe poll's own short cache window of a few seconds.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["in_call"],"properties":{"in_call":{"type":"boolean","description":"true while the user is on a call, false once it has ended.","example":true}}},"example":{"in_call":true}}}},"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/InCallState"}}},"example":{"data":{"user_id":"550e8400-e29b-41d4-a716-446655440000","in_call":true,"in_call_updated_at":"2026-08-03T09:14:22+00:00","expires_at":"2026-08-03T10:14:22+00:00","ttl_seconds":3600}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Content. `in_call` is missing or is not a boolean.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"object","properties":{"in_call":{"type":"array","items":{"type":"string"}}}}}},"example":{"message":"The in call field is required.","errors":{"in_call":["The in call field is required."]}}}}},"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}}}}},"\/user\/devices":{"get":{"tags":["Users"],"summary":"List devices for authenticated user","operationId":"listUserDevices","description":"Returns a paginated list of user devices. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"type","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by device type","example":"fcm"},{"name":"active","in":"query","required":false,"schema":{"type":"boolean"},"description":"Filter by active status","example":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Devices retrieved successfully"},"devices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440070"},"name":{"type":["string","null"],"example":"My iPhone"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"twinning_id":{"type":["string","null"],"format":"uuid","example":null},"type":{"type":"string","example":"fcm"},"token":{"type":"string","example":"abc123xyz..."},"is_active":{"type":"boolean","example":true},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2023-10-17T14:12:22Z"},"created_at":{"type":"string","format":"date-time","example":"2023-10-01T10:00:00Z"},"updated_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"}}}},"total":{"type":"integer","example":1}}},"example":{"message":"Devices retrieved successfully","devices":[{"id":"550e8400-e29b-41d4-a716-446655440070","name":"My iPhone","user_id":"550e8400-e29b-41d4-a716-446655440001","twinning_id":null,"type":"fcm","token":"abc123xyz...","is_active":true,"last_used_at":"2023-10-17T14:12:22Z","created_at":"2023-10-01T10:00:00Z","updated_at":"2023-10-17T14:12:22Z"}],"total":1}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}},"post":{"tags":["Users"],"summary":"Register a device for authenticated user","operationId":"createUserDevice","description":"Creates a new user device. Validation rules and required fields are defined in the request\nbody schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["type","token"],"properties":{"name":{"type":["string","null"],"description":"Optional device name","example":"My iPhone"},"type":{"type":"string","description":"Device type (e.g. fcm, apns)","example":"fcm"},"token":{"type":"string","description":"Device push token","example":"abc123xyz..."}}},"example":{"name":"My iPhone","type":"fcm","token":"abc123xyz..."}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"Device updated (token already existed)","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Device updated successfully"},"device":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440070"},"name":{"type":["string","null"],"example":"My iPhone"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"twinning_id":{"type":["string","null"],"format":"uuid","example":null},"type":{"type":"string","example":"fcm"},"token":{"type":"string","example":"abc123xyz..."},"is_active":{"type":"boolean","example":true},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2023-10-17T14:12:22Z"},"created_at":{"type":"string","format":"date-time","example":"2023-10-01T10:00:00Z"},"updated_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"}}}}},"example":{"message":"Device updated successfully","device":{"id":"550e8400-e29b-41d4-a716-446655440070","name":"My iPhone","user_id":"550e8400-e29b-41d4-a716-446655440001","twinning_id":null,"type":"fcm","token":"abc123xyz...","is_active":true,"last_used_at":"2023-10-17T14:12:22Z","created_at":"2023-10-01T10:00:00Z","updated_at":"2023-10-17T14:12:22Z"}}}}},"201":{"description":"Device registered successfully","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Device registered successfully"},"device":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440070"},"name":{"type":["string","null"],"example":"My iPhone"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"twinning_id":{"type":["string","null"],"format":"uuid","example":null},"type":{"type":"string","example":"fcm"},"token":{"type":"string","example":"abc123xyz..."},"is_active":{"type":"boolean","example":true},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2023-10-17T14:12:22Z"},"created_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"},"updated_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"}}}}},"example":{"message":"Device registered successfully","device":{"id":"550e8400-e29b-41d4-a716-446655440070","name":"My iPhone","user_id":"550e8400-e29b-41d4-a716-446655440001","twinning_id":null,"type":"fcm","token":"abc123xyz...","is_active":true,"last_used_at":"2023-10-17T14:12:22Z","created_at":"2023-10-17T14:12:22Z","updated_at":"2023-10-17T14:12:22Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/user\/devices\/{deviceIdOrToken}":{"patch":{"tags":["Users"],"summary":"Update a device for authenticated user","operationId":"updateUserDevice","description":"Partially updates the user device. Only the fields supplied in the request body are changed;\nothers are left untouched.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"deviceIdOrToken","in":"path","required":true,"schema":{"type":"string"},"description":"Device UUID or push token","example":"550e8400-e29b-41d4-a716-446655440070"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":["string","null"],"description":"New device name","example":"My Android"},"is_active":{"type":["boolean","null"],"description":"Whether the device should be active","example":false}}},"example":{"name":"My Android","is_active":false}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Device updated successfully"},"device":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440070"},"name":{"type":["string","null"],"example":"My Android"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"twinning_id":{"type":["string","null"],"format":"uuid","example":null},"type":{"type":"string","example":"fcm"},"token":{"type":"string","example":"abc123xyz..."},"is_active":{"type":"boolean","example":false},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2023-10-17T14:12:22Z"},"created_at":{"type":"string","format":"date-time","example":"2023-10-01T10:00:00Z"},"updated_at":{"type":"string","format":"date-time","example":"2023-10-17T14:12:22Z"}}}}},"example":{"message":"Device updated successfully","device":{"id":"550e8400-e29b-41d4-a716-446655440070","name":"My Android","user_id":"550e8400-e29b-41d4-a716-446655440001","twinning_id":null,"type":"fcm","token":"abc123xyz...","is_active":false,"last_used_at":"2023-10-17T14:12:22Z","created_at":"2023-10-01T10:00:00Z","updated_at":"2023-10-17T14:12:22Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Users"],"summary":"Delete a device for authenticated user","operationId":"deleteUserDevice","description":"Deletes the user device. Soft-delete behaviour is model-dependent: most resources are\nrecoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"deviceIdOrToken","in":"path","required":true,"schema":{"type":"string"},"description":"Device UUID or push token","example":"550e8400-e29b-41d4-a716-446655440070"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Device deleted successfully"}}},"example":{"message":"Device deleted successfully"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/dnd":{"post":{"tags":["Users"],"summary":"Set User DND","operationId":"postUserDnd","security":[{"PbxServerAuth":[]}],"description":"Triggers the action on the targeted user dnd.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"user_id":{"type":"integer","example":1},"caller_identity_id":{"type":"integer","example":1},"extension_id":{"type":"integer","example":1},"status":{"type":"boolean","example":false},"id":{"type":"integer","example":1}}},"example":{"id":1,"user_id":1,"caller_identity_id":1,"extension_id":1,"status":false}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/dnds":{"get":{"tags":["DND"],"summary":"List DND rules for the authenticated user","operationId":"listDnds","description":"Returns a paginated list of dnds. Use the standard `search`, `sort`, `page`, and `perPage`\nquery parameters; use `filter[key]=value` to narrow the result set. Multi-tenant scoping is\nenforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440002"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Caller identity the rule applies to (null for the internal-extension rule)","example":"550e8400-e29b-41d4-a716-446655440003"},"type":{"type":"string","enum":["internal","external"],"example":"external"},"status":{"type":"boolean","example":false},"created_at":{"type":["string","null"],"format":"date-time","readOnly":true},"updated_at":{"type":["string","null"],"format":"date-time","readOnly":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440002","user_id":"550e8400-e29b-41d4-a716-446655440001","caller_identity_id":"550e8400-e29b-41d4-a716-446655440003","type":"external","status":false}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/users\/{user}\/dnds":{"get":{"tags":["DND"],"summary":"List DNDs for a user","operationId":"getDndUserDndsIndex","description":"Returns the dnd user dnds index identified by the path parameter. Multi-tenant scoping is\nenforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"caller_identity_id":{"type":["integer","null"],"example":1},"extension_id":{"type":["integer","null"],"example":1},"status":{"type":"boolean","example":false}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","caller_identity_id":1,"extension_id":1,"status":false}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["DND"],"summary":"Create a DND for a user","operationId":"postDndUserDndsIndex","description":"Creates a new dnd user dnds index. Validation rules and required fields are defined in the\nrequest body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["type","status"],"properties":{"type":{"type":"string","enum":["internal","external"],"description":"`internal` toggles DND on the user's internal extension; `external`\ntoggles a per-caller-identity rule. When `type=external`, `caller_identity_id` is required.\n","example":"external"},"caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Required when `type=external`. Omit when `type=internal`.","example":"550e8400-e29b-41d4-a716-446655440003"},"status":{"type":"boolean","description":"Whether DND is enabled","example":true}}},"example":{"type":"external","caller_identity_id":"550e8400-e29b-41d4-a716-446655440003","status":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"caller_identity_id":{"type":["integer","null"],"example":1},"extension_id":{"type":["integer","null"],"example":1},"status":{"type":"boolean","example":false}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","caller_identity_id":1,"extension_id":1,"status":false}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/dnds\/{userDnd}":{"put":{"tags":["DND"],"summary":"Update a DND for a user","operationId":"updateDndUserDndsSpecific","description":"Replaces the dnd user dnds specific with the fields supplied in the request body. Fields\nomitted from the body are reset to their defaults.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"dnd","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the DND","example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"description":"Update only accepts toggling `status`; other fields are ignored.","properties":{"status":{"type":"boolean","description":"Whether DND should be enabled","example":true}}},"example":{"status":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"caller_identity_id":{"type":["integer","null"],"example":1},"extension_id":{"type":["integer","null"],"example":1},"status":{"type":"boolean","example":true}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","caller_identity_id":1,"extension_id":1,"status":true}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/dnds\/bulk":{"post":{"tags":["DND"],"summary":"Bulk-update DND rules for a user","operationId":"postDndUserDndsBulk","description":"Creates a new dnd user dnds bulk. Validation rules and required fields are defined in the\nrequest body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["dnds"],"properties":{"dnds":{"type":"array","description":"Array of DND rules to apply","items":{"type":"object","required":["type","status"],"properties":{"type":{"type":"string","enum":["internal","external"]},"caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Required when `type=external`"},"status":{"type":"boolean"}}}}}},"example":{"dnds":[{"type":"internal","status":true},{"type":"external","caller_identity_id":"550e8400-e29b-41d4-a716-446655440003","status":false}]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"status":{"type":"boolean","example":true}}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","status":true}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/dnds\/all-external":{"post":{"tags":["DND"],"summary":"Toggle DND on every external extension of a user","operationId":"postDndUserDndsAllExternal","description":"Creates a new dnd user dnds all external. Validation rules and required fields are defined\nin the request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"DND status to apply to all external extensions","example":true}}},"example":{"status":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"updated":{"type":"integer","description":"Number of DND records updated","example":3}}}}},"example":{"data":{"updated":3}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/dnds\/all":{"post":{"tags":["DND"],"summary":"Toggle DND on every extension of a user","operationId":"postDndUserDndsAll","description":"Creates a new dnd user dnds all. Validation rules and required fields are defined in the\nrequest body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"DND status to apply to all extensions","example":true}}},"example":{"status":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"updated":{"type":"integer","description":"Number of DND records updated","example":5}}}}},"example":{"data":{"updated":5}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/forwards":{"get":{"tags":["Users"],"summary":"List forwards for a user","operationId":"getUserUserForwardsIndex","description":"Returns the user user forwards index identified by the path parameter. Multi-tenant scoping\nis enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"type":{"type":"string","example":"unconditional"},"destination":{"type":"string","example":"+32499123456"},"status":{"type":"boolean","example":true}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440010","user_id":"550e8400-e29b-41d4-a716-446655440001","type":"unconditional","destination":"+32499123456","status":true}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["Users"],"summary":"Create a forward for a user","operationId":"postUserUserForwardsIndex","description":"Creates a new user user forwards index. Validation rules and required fields are defined in\nthe request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["enabled","event","target"],"properties":{"enabled":{"type":"boolean","description":"Whether this forward rule is active","example":true},"name":{"type":["string","null"],"description":"Optional human-readable name used to identify the forward","example":"Mobile"},"event":{"type":"string","enum":["busy","no_answer","unconditional","unreachable"],"description":"When the forward should trigger","example":"no_answer"},"target":{"type":"string","enum":["phone_number","extension","voicemail"],"description":"Where the forward routes the call","example":"phone_number"},"target_options":{"type":"object","description":"Target-type-specific configuration","additionalProperties":true,"example":{"phone_number":"+12125550100"}},"caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Scope the forward to a specific caller identity (null = all)","example":null}}},"example":{"enabled":true,"event":"no_answer","target":"phone_number","target_options":{"phone_number":"+12125550100"},"caller_identity_id":null}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"type":{"type":"string","example":"unconditional"},"destination":{"type":"string","example":"+32499123456"},"status":{"type":"boolean","example":true}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440010","user_id":"550e8400-e29b-41d4-a716-446655440001","type":"unconditional","destination":"+32499123456","status":true}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/forwards\/{forward}":{"put":{"tags":["Users"],"summary":"Update a forward for a user","operationId":"updateUserUserForwardsSpecific","description":"Replaces the user user forwards specific with the fields supplied in the request body.\nFields omitted from the body are reset to their defaults.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"forward","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the forward","example":"550e8400-e29b-41d4-a716-446655440010"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["enabled"],"description":"Update accepts toggling the `enabled` flag and changing the `name`; other fields are ignored.","properties":{"enabled":{"type":"boolean","example":false},"name":{"type":["string","null"],"description":"Optional human-readable name used to identify the forward","example":"Mobile"}}},"example":{"enabled":false,"name":"Mobile"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"enabled":{"type":"boolean"},"event":{"type":"string","enum":["busy","no_answer","unconditional","unreachable"]},"target":{"type":"string","enum":["phone_number","extension","voicemail"]},"target_options":{"type":"object","additionalProperties":true},"caller_identity_id":{"type":["string","null"],"format":"uuid"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440010","user_id":"550e8400-e29b-41d4-a716-446655440001","enabled":false,"event":"no_answer","target":"phone_number","target_options":{"phone_number":"+12125550100"},"caller_identity_id":null}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Users"],"summary":"Delete a forward for a user","operationId":"deleteUserUserForwardsSpecific","description":"Deletes the user user forwards specific. Soft-delete behaviour is model-dependent: most\nresources are recoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"forward","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the forward","example":"550e8400-e29b-41d4-a716-446655440010"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/favorite-users":{"post":{"tags":["Users"],"summary":"Add a favorite user (user)","operationId":"createUserFavoriteUser","description":"Mark another user as a favorite for the given user. The favorited user must\nbelong to the same PBX as the owning user, and the same favorite cannot be\nadded twice. The owning user is taken from the `{user}` path segment and the\nPBX is derived server-side; neither `user_id` nor `pbx_id` may be sent in the\nbody.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"Identifier of the user who owns the favorites list","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["favorite_user_id"],"properties":{"favorite_user_id":{"type":"string","format":"uuid","description":"Identifier of the user to mark as a favorite. Must reference an\nexisting user in the same PBX and must not already be a favorite\nof the owning user.\n"}}},"example":{"favorite_user_id":"550e8400-e29b-41d4-a716-446655440001"}}}},"responses":{"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"favorite_user_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440040","user_id":"550e8400-e29b-41d4-a716-446655440000","favorite_user_id":"550e8400-e29b-41d4-a716-446655440001","created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/favorite-users\/{favorite_user}":{"delete":{"tags":["Users"],"summary":"Remove a favorite user (user)","operationId":"deleteUserFavoriteUser","description":"Remove a user from the owning user's favorites list. The owning user is\ntaken from the `{user}` path segment, and the `{favorite_user}` path segment\nis the identifier of the favorited user (not the favorite record id). If no\nmatching favorite exists for the pair, a `404` is returned.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"Identifier of the user who owns the favorites list","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"favorite_user","in":"path","required":true,"description":"Identifier of the favorited user to remove","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}}],"responses":{"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/phone-buttons\/resolved":{"get":{"tags":["Users"],"summary":"Get resolved phone buttons for a user","operationId":"getUserPhoneButtonsResolved","description":"Returns the user phone buttons resolved identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer","example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"}}}}}},"example":{"data":[{"position":1,"type":"speed_dial","value":"101","label":"Front Desk"},{"position":2,"type":"empty","value":null,"label":null}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/phone-buttons\/resolved-detailed":{"get":{"tags":["Users"],"summary":"Get resolved detailed phone buttons for a user","operationId":"getUserPhoneButtonsResolvedDetailed","description":"Returns the user phone buttons resolved detailed identified by the path parameter.\nMulti-tenant scoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer","example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"},"details":{"type":["object","null"],"description":"Additional resolved details for the button target"}}}}}},"example":{"data":[{"position":1,"type":"speed_dial","value":"101","label":"Front Desk","details":{"extension_number":"101","user_name":"Jane Smith","status":"available"}}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/phone-buttons\/preview-config":{"get":{"tags":["Users"],"summary":"Get phone buttons preview config for a user","operationId":"getUserPhoneButtonsPreviewConfig","description":"Returns the user phone buttons preview config identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Phone button preview configuration","properties":{"model":{"type":["string","null"],"example":"Yealink T46S"},"total_buttons":{"type":"integer","example":27},"buttons":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer","example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"}}}}}}}},"example":{"data":{"model":"Yealink T46S","total_buttons":27,"buttons":[{"position":1,"type":"speed_dial","value":"101","label":"Front Desk"}]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/phone-buttons":{"get":{"tags":["Users"],"summary":"List phone buttons for a user","operationId":"getUserPhoneButtonsIndex","description":"Returns the user phone buttons index identified by the path parameter. Multi-tenant scoping\nis enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"number":{"type":"integer","minimum":1,"example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440030","user_id":"550e8400-e29b-41d4-a716-446655440001","number":1,"type":"speed_dial","value":"101","label":"Front Desk"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["Users"],"summary":"Create a phone button for a user","operationId":"postUserPhoneButtonsIndex","description":"Creates a new user phone buttons index. Validation rules and required fields are defined in\nthe request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["number","type"],"description":"Phone button position is `number` (1-based, max determined by the\ntarget device). The button's `type` drives which optional `target_*`\nfields are required.\n","properties":{"number":{"type":"integer","minimum":1,"description":"1-based button position on the phone","example":1},"label":{"type":["string","null"],"description":"Required when `type` is anything other than `none`","example":"Front Desk"},"type":{"type":"string","description":"Button kind (see PhoneButton type registry for the full enum)","example":"speed_dial_extension"},"target_user_id":{"type":["string","null"],"format":"uuid","description":"Target user (when applicable to the button type)"},"target_extension_id":{"type":["string","null"],"format":"uuid","description":"Target extension (when applicable)"},"caller_identity_id":{"type":["string","null"],"format":"uuid","description":"Caller identity used (when applicable)"},"phone_number":{"type":["string","null"],"description":"Raw phone number to dial (for external speed dials)"},"multicast_id":{"type":["string","null"],"format":"uuid"},"status_id":{"type":["string","null"],"format":"uuid","description":"Tempus status (for status-toggle buttons)"},"call_flow_id":{"type":["string","null"],"format":"uuid"},"forward_type":{"type":["string","null"]},"forward_caller_identity_id":{"type":["string","null"],"format":"uuid"},"function_action":{"type":["string","null"],"description":"Built-in function (e.g. `dnd`, `voicemail`)"},"contact_phone_number_id":{"type":["string","null"],"format":"uuid"},"editable":{"type":"boolean"},"sync_source":{"type":"string","enum":["manual","provision"]}}},"example":{"number":1,"type":"speed_dial_extension","label":"Front Desk","target_extension_id":"550e8400-e29b-41d4-a716-446655440010"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"number":{"type":"integer","minimum":1,"example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440030","user_id":"550e8400-e29b-41d4-a716-446655440001","number":1,"type":"speed_dial","value":"101","label":"Front Desk"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/phone-buttons\/{phoneButtonId}":{"get":{"tags":["Users"],"summary":"Get a phone button for a user","operationId":"getUserPhoneButtonsSpecific","description":"Returns the user phone buttons specific identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"phoneButtonId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the phone button","example":"550e8400-e29b-41d4-a716-446655440030"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"number":{"type":"integer","minimum":1,"example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Front Desk"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440030","user_id":"550e8400-e29b-41d4-a716-446655440001","number":1,"type":"speed_dial","value":"101","label":"Front Desk"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["Users"],"summary":"Replace a phone button for a user","operationId":"updateUserPhoneButtonsSpecific","description":"Replaces the user phone buttons specific with the fields supplied in the request body.\nFields omitted from the body are reset to their defaults.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"phoneButtonId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the phone button","example":"550e8400-e29b-41d4-a716-446655440030"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","description":"Same shape as POST; all fields support `sometimes` for partial updates.","properties":{"number":{"type":"integer","minimum":1,"example":1},"label":{"type":["string","null"],"example":"Support"},"type":{"type":"string","example":"speed_dial_extension"},"target_user_id":{"type":["string","null"],"format":"uuid"},"target_extension_id":{"type":["string","null"],"format":"uuid"},"caller_identity_id":{"type":["string","null"],"format":"uuid"},"phone_number":{"type":["string","null"]},"function_action":{"type":["string","null"]}}},"example":{"label":"Support","target_extension_id":"550e8400-e29b-41d4-a716-446655440011"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"number":{"type":"integer","minimum":1,"example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"102"},"label":{"type":["string","null"],"example":"Support"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440030","user_id":"550e8400-e29b-41d4-a716-446655440001","number":1,"type":"speed_dial","value":"102","label":"Support"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"patch":{"tags":["Users"],"summary":"Partially update a phone button for a user","operationId":"patchUserPhoneButtonsSpecific","description":"Partially updates the user phone buttons specific. Only the fields supplied in the request\nbody are changed; others are left untouched.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"phoneButtonId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the phone button","example":"550e8400-e29b-41d4-a716-446655440030"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"label":{"type":["string","null"],"example":"Reception"}}},"example":{"label":"Reception"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"number":{"type":"integer","minimum":1,"example":1},"type":{"type":"string","example":"speed_dial"},"value":{"type":["string","null"],"example":"101"},"label":{"type":["string","null"],"example":"Reception"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440030","user_id":"550e8400-e29b-41d4-a716-446655440001","number":1,"type":"speed_dial","value":"101","label":"Reception"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Users"],"summary":"Delete a phone button for a user","operationId":"deleteUserPhoneButtonsSpecific","description":"Deletes the user phone buttons specific. Soft-delete behaviour is model-dependent: most\nresources are recoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"phoneButtonId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the phone button","example":"550e8400-e29b-41d4-a716-446655440030"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/user-settings":{"get":{"tags":["Users"],"summary":"List settings for a user","operationId":"getUserUserSettingsIndex","description":"Returns the user user settings index identified by the path parameter. Multi-tenant scoping\nis enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"type":"notifications","settings":"{\"email\":true,\"push\":false}"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["Users"],"summary":"Create a setting for a user","operationId":"postUserUserSettingsIndex","description":"Creates a new user user settings index. Validation rules and required fields are defined in\nthe request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["type","settings"],"properties":{"type":{"type":"string","description":"Setting type key","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}},"example":{"type":"notifications","settings":"{\"notifications\":{\"email\":true,\"push\":false}}"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}}}},"example":{"data":{"type":"notifications","settings":"{\"email\":true,\"push\":false}"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/user-settings\/{type}":{"get":{"tags":["Users"],"summary":"Get a setting for a user by type","operationId":"getUserUserSettingsSpecific","description":"Returns the user user settings specific identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"type","in":"path","required":true,"schema":{"type":"string"},"description":"The setting type key","example":"notifications"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}}}},"example":{"data":{"type":"notifications","settings":"{\\\"email\\\":true,\\\"push\\\":false}"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["Users"],"summary":"Replace a setting for a user by type","operationId":"updateUserUserSettingsSpecific","description":"Replaces the user user settings specific with the fields supplied in the request body.\nFields omitted from the body are reset to their defaults.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"type","in":"path","required":true,"schema":{"type":"string"},"description":"The setting type key","example":"notifications"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["settings"],"properties":{"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}},"example":{"settings":"{\"email_alerts\":true,\"sms_alerts\":false,\"daily_digest\":\"08:00\"}"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}}}},"example":{"data":{"type":"notifications","settings":"{\"email\":false,\"push\":true}"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"patch":{"tags":["Users"],"summary":"Partially update a setting for a user by type","operationId":"patchUserUserSettingsSpecific","description":"Partially updates the user user settings specific. Only the fields supplied in the request\nbody are changed; others are left untouched.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"type","in":"path","required":true,"schema":{"type":"string"},"description":"The setting type key","example":"notifications"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}},"example":{"settings":"{\"daily_digest\":\"09:00\"}"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","example":"notifications"},"settings":{"type":"string","description":"JSON-encoded settings payload (string column on the user_settings table)"}}}}},"example":{"data":{"type":"notifications","settings":"{\"email\":false,\"push\":true}"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Users"],"summary":"Delete a setting for a user by type","operationId":"deleteUserUserSettingsSpecific","description":"Deletes the user user settings specific. Soft-delete behaviour is model-dependent: most\nresources are recoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"type","in":"path","required":true,"schema":{"type":"string"},"description":"The setting type key","example":"notifications"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/twinnings":{"get":{"tags":["Twinning"],"summary":"List a user's twinnings (user)","operationId":"listUserTwinnings","description":"List the twinnings that belong to the given user. Results are paginated.\n\nThe following Spatie QueryBuilder filters are supported (exact match):\n`filter[status]`, `filter[phone_number]`, `filter[delay]`,\n`filter[sync_source]` and `filter[type]`. Sorting is allowed on the same\nfields; prefix a field with `-` for descending order, for example\n`sort=-delay`.\n\nWhen a twinning has Fixed-Mobile Convergence (FMC) enabled together with a\nbackup phone number, the response also includes a derived read-only entry\nfor that backup number. The derived entry carries a generated `id` and is\nnot a separately stored record.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"page","in":"query","required":false,"description":"Page number to fetch. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to `25`, maximum `100`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"example":25},{"name":"sort","in":"query","description":"Field to sort by. Allowed values are `status`, `phone_number`, `delay`,\n`sync_source` and `type`. Prefix with `-` for descending order.\n","schema":{"type":"string","example":"-delay"}},{"name":"filter[key]","in":"query","description":"<\/br>The filter key can be one of: `status`, `phone_number`, `delay`,\n`sync_source` or `type` (exact match). <\/br>The filter value can be any\nstring. <\/br><\/br> It is also possible to apply multiple filters using\nthe following format: filter[status]=enabled&filter[type]=mobile\n","schema":{"type":"string"},"example":"enabled"}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Twinning"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","status":"enabled","phone_number":"+12125550100","delay":5,"sync_source":"manual","type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}],"links":{"first":"https:\/\/cockpit.voxbi.com\/api\/v1\/users\/550e8400-e29b-41d4-a716-446655440001\/twinnings?page=1","last":"https:\/\/cockpit.voxbi.com\/api\/v1\/users\/550e8400-e29b-41d4-a716-446655440001\/twinnings?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":"https:\/\/cockpit.voxbi.com\/api\/v1\/users\/550e8400-e29b-41d4-a716-446655440001\/twinnings?page=1","label":"1","active":true}],"path":"https:\/\/cockpit.voxbi.com\/api\/v1\/users\/550e8400-e29b-41d4-a716-446655440001\/twinnings","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["Twinning"],"summary":"Create a twinning for a user (user)","operationId":"createUserTwinning","description":"Create a twinning for the given user. The `user_id` is taken from the path\nand the `sync_source` is always set to `manual` server-side; neither may be\nsupplied in the request body.\n\nWhether `phone_number` is required depends on the combination of `type` and\n`dial_strategy` (for example, a `voip_only` mobile twinning does not require\na phone number). A user may hold at most one `teams`-type twinning and at\nmost one `voip_only` twinning. `backup_phone_number` is only accepted when\n`fmc_enabled` is true and the twinning is FMC-eligible (mobile type).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status","delay","type","dial_strategy"],"properties":{"status":{"type":"string","enum":["enabled","disabled"],"description":"Whether the twinning is active.","example":"enabled"},"phone_number":{"type":"string","maxLength":24,"description":"Twinned destination phone number (E.164 preferred). Required for\nstrategies that dial a number; ignored for Teams or VoIP-only\nconfigurations.\n","example":"+12125550100"},"delay":{"type":"integer","minimum":0,"description":"Seconds to wait before the twinning leg starts ringing.","example":5},"type":{"type":"string","enum":["mobile","teams"],"description":"Channel used to reach the twinned destination.","example":"mobile"},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"],"description":"How the mobile leg is dialed.","example":"voip_and_gsm_fallback"},"fmc_enabled":{"type":"boolean","description":"Whether Fixed-Mobile Convergence is enabled.","example":false},"backup_phone_number":{"type":["string","null"],"maxLength":24,"description":"Backup number used when the primary FMC leg fails. Requires fmc_enabled.","example":null}}},"example":{"status":"enabled","phone_number":"+12125550100","delay":5,"type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null}}}},"responses":{"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Twinning"}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","status":"enabled","phone_number":"+12125550100","delay":5,"sync_source":"manual","type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/twinnings\/{twinning}":{"get":{"tags":["Twinning"],"summary":"Get a user's twinning (user)","operationId":"getUserTwinning","description":"Retrieve a single twinning belonging to the given user. A twinning that does\nnot exist, or that belongs to a different user, responds with 404.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"twinning","in":"path","required":true,"description":"Twinning identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Twinning"}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","status":"enabled","phone_number":"+12125550100","delay":5,"sync_source":"manual","type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["Twinning"],"summary":"Update a user's twinning (user)","operationId":"updateUserTwinning","description":"Update a twinning belonging to the given user. Every field is optional; only\nthe fields present in the body are changed. `user_id` and `sync_source` are\nserver-managed and must not be sent.\n\nFor twinnings whose `sync_source` is `provision`, the `phone_number`, `type`\nand `dial_strategy` fields are locked: provisioned values are preserved and\nany conflicting values are rejected.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"twinning","in":"path","required":true,"description":"Twinning identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["enabled","disabled"]},"phone_number":{"type":"string","maxLength":24},"delay":{"type":"integer","minimum":0},"type":{"type":"string","enum":["mobile","teams"]},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"]},"fmc_enabled":{"type":"boolean"},"backup_phone_number":{"type":["string","null"],"maxLength":24}}},"example":{"status":"disabled","delay":10}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Twinning"}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","status":"disabled","phone_number":"+12125550100","delay":10,"sync_source":"manual","type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"patch":{"tags":["Twinning"],"summary":"Update a user's twinning (user)","operationId":"patchUserTwinning","description":"Alias of the `PUT` update with identical request shape and validation rules.\nOnly the fields present in the body are changed; `user_id` and `sync_source`\nare server-managed. Provisioned twinnings keep their locked\n`phone_number`, `type` and `dial_strategy` values.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"twinning","in":"path","required":true,"description":"Twinning identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["enabled","disabled"]},"phone_number":{"type":"string","maxLength":24},"delay":{"type":"integer","minimum":0},"type":{"type":"string","enum":["mobile","teams"]},"dial_strategy":{"type":"string","enum":["gsm_only","voip_only","voip_and_gsm_fallback"]},"fmc_enabled":{"type":"boolean"},"backup_phone_number":{"type":["string","null"],"maxLength":24}}},"example":{"status":"enabled"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Twinning"}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","status":"enabled","phone_number":"+12125550100","delay":5,"sync_source":"manual","type":"mobile","dial_strategy":"voip_and_gsm_fallback","fmc_enabled":false,"backup_phone_number":null,"created_at":"2024-03-01T08:29:07Z","updated_at":"2024-03-01T08:29:07Z"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Twinning"],"summary":"Delete a user's twinning (user)","operationId":"deleteUserTwinning","description":"Delete a twinning belonging to the given user. A twinning whose\n`sync_source` is `provision` cannot be removed through this endpoint and\nresponds with 422.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"description":"User identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"twinning","in":"path","required":true,"description":"Twinning identifier","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/user-groups":{"get":{"tags":["Users"],"summary":"List user-groups for a user","operationId":"getUserUserUserGroupsIndex","description":"Returns the user user user groups index identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"position":{"type":"integer","example":1}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","position":1}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"post":{"tags":["Users"],"summary":"Add a user-group to a user","operationId":"postUserUserUserGroupsIndex","description":"Creates a new user user user groups index. Validation rules and required fields are defined\nin the request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"user_group_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"position":{"type":"integer","example":1}}},"example":{"user_group_id":"550e8400-e29b-41d4-a716-446655440020","position":1}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"position":{"type":"integer","example":1}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","position":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/users\/{user}\/user-groups\/{userGroup}":{"get":{"tags":["Users"],"summary":"Get a user-group for a user","operationId":"getUserUserUserGroupsSpecific","description":"Returns the user user user groups specific identified by the path parameter. Multi-tenant\nscoping is enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"userGroup","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"position":{"type":"integer","example":1}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","position":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"patch":{"tags":["Users"],"summary":"Partially update a user-group for a user","operationId":"updateUserUserUserGroupsSpecific","description":"Partially updates the user user user groups specific. Only the fields supplied in the\nrequest body are changed; others are left untouched.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"userGroup","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"position":{"type":"integer","example":2}}},"example":{"position":2}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"position":{"type":"integer","example":2}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","position":2}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["Users"],"summary":"Remove a user-group from a user","operationId":"deleteUserUserUserGroupsSpecific","description":"Deletes the user user user groups specific. Soft-delete behaviour is model-dependent: most\nresources are recoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"userGroup","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"Deleted (no content)"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/users\/{user}\/right-to-disconnect":{"get":{"tags":["Users"],"summary":"Get right-to-disconnect settings for a user","operationId":"getUserRightToDisconnect","description":"Returns the user right to disconnect identified by the path parameter. Multi-tenant scoping\nis enforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean","example":true},"schedule":{"type":["object","null"],"description":"Right-to-disconnect schedule configuration"}}}}},"example":{"data":{"enabled":true,"schedule":{"weekdays":{"start":"18:00","end":"08:00"},"weekend":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["Users"],"summary":"Update right-to-disconnect settings for a user","operationId":"updateUserRightToDisconnect","description":"Replaces the user right to disconnect with the fields supplied in the request body. Fields\nomitted from the body are reset to their defaults.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"user","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","example":true},"schedule":{"type":["object","null"],"description":"Right-to-disconnect schedule configuration"}}},"example":{"enabled":true}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean","example":true},"schedule":{"type":["object","null"]}}}}},"example":{"data":{"enabled":true,"schedule":{"weekdays":{"start":"18:00","end":"08:00"},"weekend":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/user-groups":{"get":{"tags":["UserGroups"],"summary":"List user groups","operationId":"listUserGroups","description":"Returns a paginated list of user groups. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"user_id":{"type":"string","format":"uuid","description":"Owner user (a user-group belongs to one user)","example":"550e8400-e29b-41d4-a716-446655440001"},"position":{"type":"integer","example":1},"users":{"type":"array","description":"Member user identifiers (when included)","items":{"type":"string","format":"uuid"}}}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","user_id":"550e8400-e29b-41d4-a716-446655440001","position":1},{"id":"550e8400-e29b-41d4-a716-446655440021","name":"Support Team","user_id":"550e8400-e29b-41d4-a716-446655440001","position":2}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}},"post":{"tags":["UserGroups"],"summary":"Create a user-group","operationId":"createUserGroup","description":"Creates a new user group. Validation rules and required fields are defined in the request\nbody schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name","user_ids"],"properties":{"name":{"type":"string","example":"Sales Team"},"user_ids":{"type":"array","description":"UUIDs of users to add to this group (must belong to the same PBX as the authenticated user)","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]}}},"example":{"name":"Sales Team","user_ids":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"data":{"type":"object","properties":{"created_entry":{"type":"object","description":"The newly-created user-group resource","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"user_id":{"type":"string","format":"uuid"},"users":{"type":"array","items":{"type":"string","format":"uuid"}}}},"non_added_user_ids":{"type":"array","description":"User IDs that were not added (e.g. wrong PBX)","items":{"type":"string","format":"uuid"}}}}}},"example":{"success":true,"message":"User group created successfully","data":{"created_entry":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","user_id":"550e8400-e29b-41d4-a716-446655440001","users":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]},"non_added_user_ids":[]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/user-groups\/update-positions":{"post":{"tags":["UserGroups"],"summary":"Update positions of user-groups","operationId":"postUserGroupUpdatePositions","description":"Creates a new user group update positions. Validation rules and required fields are defined\nin the request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","required":["id","position"],"properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"position":{"type":"integer","example":1}}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440020","position":1}]}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Positions updated successfully"}}},"example":{"message":"Positions updated successfully"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/user-groups\/{userGroupId}":{"get":{"tags":["UserGroups"],"summary":"Get an user-group","operationId":"getUserGroup","description":"Returns the user group identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team"},"position":{"type":"integer","example":1},"pbx_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team","position":1,"pbx_id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"patch":{"tags":["UserGroups"],"summary":"Partially update a user-group","operationId":"updateUserGroup","description":"Partially updates the user group. Only the fields supplied in the request body are changed;\nothers are left untouched.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name","user_ids"],"properties":{"name":{"type":"string","example":"Sales Team Updated"},"user_ids":{"type":"array","description":"Full replacement set of member user IDs","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]},"position":{"type":"integer","example":2}}},"example":{"name":"Sales Team Updated","user_ids":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"],"position":2}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"name":{"type":"string","example":"Sales Team Updated"},"position":{"type":"integer","example":2},"pbx_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}},"example":{"data":{"id":"550e8400-e29b-41d4-a716-446655440020","name":"Sales Team Updated","position":2,"pbx_id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["UserGroups"],"summary":"Delete a user-group","operationId":"deleteUserGroup","description":"Deletes the user group. Soft-delete behaviour is model-dependent: most resources are\nrecoverable via the restore endpoint, while a few are hard-deleted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User-group deleted successfully"}}},"example":{"message":"User-group deleted successfully"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/user-groups\/{userGroupId}\/add-users":{"post":{"tags":["UserGroups"],"summary":"Add users to a user-group","operationId":"postUserGroupAddUsers","description":"Creates a new user group add users. Validation rules and required fields are defined in the\nrequest body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["user_ids"],"properties":{"user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"]}}},"example":{"user_ids":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Users added successfully"}}},"example":{"message":"Users added successfully"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/user-groups\/{userGroupId}\/remove-users":{"post":{"tags":["UserGroups"],"summary":"Remove users from a user-group","operationId":"postUserGroupRemoveUsers","description":"Creates a new user group remove users. Validation rules and required fields are defined in\nthe request body schema below.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the user-group","example":"550e8400-e29b-41d4-a716-446655440020"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["user_ids"],"properties":{"user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"]}}},"example":{"user_ids":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"]}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Users removed successfully"}}},"example":{"message":"Users removed successfully"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/pools\/{id}\/users":{"get":{"tags":["Pools"],"summary":"List users in a pool","operationId":"getPoolUsers","description":"Returns the pool users identified by the path parameter. Multi-tenant scoping is enforced:\nthe caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the pool","example":"550e8400-e29b-41d4-a716-446655440050"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"first_name":{"type":"string","example":"John"},"last_name":{"type":"string","example":"Doe"},"email":{"type":"string","example":"john.doe@example.com"},"status":{"type":"string","example":"enabled"}}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440001","first_name":"John","last_name":"Doe","email":"john.doe@example.com","status":"enabled"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/voxbi-group-tabs":{"get":{"tags":["VoxbiGroupTabs"],"summary":"List all voxbi group tabs","operationId":"listVoxbiGroupTabs","description":"Returns a paginated list of voxbi group tabs. Use the standard `search`, `sort`, `page`, and\n`perPage` query parameters; use `filter[key]=value` to narrow the result set. Multi-tenant\nscoping is enforced.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A Voxbi group tab as it appears in the authenticated user's Voxbi interface.\nEach tab is backed by a `Group` and surfaces the set of fellow members the\ncaller can monitor and interact with. The `users` array lists only the user\nidentifiers that are relevant for the current caller: members that have at\nleast one extension assigned, with the authenticated user themselves excluded\n(a user never appears in their own tab).\n","required":["id","pbx_id","name","description","users"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the underlying group that backs this tab.","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the Pbx (tenant) that owns this group.","example":"550e8400-e29b-41d4-a716-446655440001"},"name":{"type":"string","description":"Display name of the group shown as the tab label.","example":"Sales Team"},"description":{"type":["string","null"],"description":"Optional free-form description of the group.","example":"All sales representatives"},"users":{"type":"array","description":"Identifiers of the group members that are visible to the authenticated\ncaller in this tab. The list is filtered to members that have at least\none extension assigned, and the authenticated user's own identifier is\nalways excluded. May be empty when no other eligible members exist.\n","items":{"type":"string","format":"uuid","description":"Identifier of a fellow group member with an assigned extension.","example":"550e8400-e29b-41d4-a716-446655440002"}}}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440060","pbx_id":"550e8400-e29b-41d4-a716-446655440000","name":"Sales Team","description":"All sales representatives","users":["550e8400-e29b-41d4-a716-446655440002"]}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/change-status":{"post":{"tags":["Users"],"summary":"Change presence status for the authenticated user (user)","operationId":"changeUserStatus","description":"Record a presence status change for the authenticated user. This opens a new\ntimepoint for the selected status and, when the status is mapped to the\nexternal Tempus system, propagates the change and returns the updated\nwork-time totals.\n\n`status_id` accepts either a Cockpit status UUID or an external Tempus mapping\nidentifier, which is resolved to the matching Cockpit status server-side. The\nuser and PBX are always derived from the authenticated token and must not be\nsent in the request body.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status_id"],"properties":{"status_id":{"type":"string","description":"Target status. A Cockpit status UUID, or an external Tempus\nmapping identifier that is resolved server-side.\n","example":"550e8400-e29b-41d4-a716-446655440000"},"location_id":{"type":["string","null"],"format":"uuid","description":"Optional location to associate with the status. Must reference a\nlocation enabled for presence status.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"sub_status_ids":{"type":["array","null"],"description":"Optional sub-status identifiers linked to the selected status.\nA single value unless the status allows multiselect; required\nwhen the status mandates a sub-status selection.\n","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440020"]},"sources":{"type":["array","null"],"description":"Origin channels for the status change.","items":{"type":"string"},"example":["mobile"]},"triggers":{"type":["array","null"],"description":"Triggers that initiated the status change.","items":{"type":"string"},"example":["manual"]},"meta_data":{"type":["object","null"],"additionalProperties":true,"description":"Arbitrary metadata, stored verbatim on the time point.\n\nGPS coordinates may be sent here (as `lat`\/`lng`,\n`latitude`\/`longitude`, or `gpsLat`\/`gpsLong`, with an optional\n`accuracy` and `gpsTimestamp`) or in `gpsData`. Either way the\nserver normalises them onto the time point as `device_gps` and\ncompares them with the selected `location_id`, exposing the\nresult as `location_check`. See the `TempusTimePoint` model.\n\nCoordinates sent here are recorded as-is. They are never\nreplaced by the coordinates configured on `location_id`, which\nis what makes a `location_id` that disagrees with the device's\nposition detectable afterwards.\n","example":{"lat":49.6116,"lng":6.1319}},"gpsData":{"type":["object","null"],"additionalProperties":true,"description":"The device's GPS fix, as clients have historically sent it. An\nalternative container for the coordinates described under\n`meta_data`: both are accepted, both are stored, and sending\nboth no longer discards this one. Also forwarded to the\ndownstream Tempus webhook.\n\nValues are read tolerantly. A fix that is unusable (only one of\nthe pair, non-numeric, or out of range) does not fail the\nrequest: it is stored as sent, and `location_check.reason`\nreports `no_device_gps`.\n","example":{"gpsLat":49.6116,"gpsLong":6.1319,"accuracy":12.5,"gpsTimestamp":1783418859289}},"comment":{"type":["string","null"],"maxLength":255,"description":"Optional free-text comment.","example":"Starting morning shift"}}},"example":{"status_id":"550e8400-e29b-41d4-a716-446655440000","location_id":"550e8400-e29b-41d4-a716-446655440010","sub_status_ids":["550e8400-e29b-41d4-a716-446655440020"],"sources":["mobile"],"triggers":["manual"],"meta_data":{"app_version":"3.4.1"},"gpsData":{"gpsLat":49.6116,"gpsLong":6.1319,"accuracy":12.5,"gpsTimestamp":1783418859289},"comment":"Starting morning shift"}}}},"responses":{"200":{"description":"Status change processed without opening a new time point: either the\nsubmit collapsed onto the already-open time point (same status and same\n`location_id` inside the same clock minute), or the status carries no\nTempus mapping id so nothing was synced downstream. In the latter case\n`ui.data` is an empty array.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"ui":{"type":"object","properties":{"data":{"oneOf":[{"$ref":"#\/components\/schemas\/TempusTimePoint"},{"type":"array","maxItems":0,"items":{"type":"object"}}]}}},"workTimes":{"type":"object","additionalProperties":true},"message":{"type":["string","null"]}}},"example":{"ui":{"data":[]},"workTimes":{"daily":"08:00:00","weekly":"40:00:00"},"message":"Status applied"}}}},"201":{"description":"A new time point was opened. `ui.data` is the created time point,\nincluding `device_gps` (the coordinates the client sent, stored as sent)\nand `location_check` (how they compare with the selected location's\ngeofence).\n","content":{"application\/json":{"schema":{"type":"object","properties":{"ui":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusTimePoint"}}},"workTimes":{"type":"object","additionalProperties":true}}},"example":{"ui":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","user_id":"550e8400-e29b-41d4-a716-446655440002","status_id":"550e8400-e29b-41d4-a716-446655440003","location_id":"550e8400-e29b-41d4-a716-446655440010","start_time":"2026-07-07T10:07:39.000000Z","end_time":null,"sources":["mobile"],"triggers":["manual"],"meta_data":{"app_version":"3.4.1","gpsLat":49.95,"gpsLong":6.133,"source":"api_v1","device_gps":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289},"location_check":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null}},"is_synced":false,"location":{"id":"550e8400-e29b-41d4-a716-446655440010","name":"HQ Luxembourg","latitude":49.6008,"longitude":6.133,"geofence_radius_m":150,"is_fixed_location":true},"device_gps":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289},"location_check":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null},"created_at":"2026-07-07T10:07:39.000000Z","updated_at":"2026-07-07T10:07:39.000000Z"}},"workTimes":{"daily":"08:00:00","weekly":"40:00:00"}}}}},"409":{"description":"Another status change for this employee is already in progress and could\nnot be resolved. Retry once after a short delay.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"null"},"errors":{"type":"array","items":{"type":"string"}},"message":{"type":"string"}}},"example":{"data":null,"errors":["Another status change is already in progress. Please try again."],"message":"Status change failed."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/timepoints":{"get":{"tags":["Users"],"summary":"List presence timepoints for the authenticated user (user)","operationId":"listUserTimepoints","description":"Return a paginated list of presence timepoints (status changes recorded over\ntime) scoped to the authenticated user's PBX. Results are sorted by\n`start_time` descending by default.\n\nFiltering and sorting follow the Spatie query-builder convention: filters are\npassed as `filter[<field>]` and sorts as a comma-separated `sort` value where\na leading `-` denotes descending order.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"per_page","in":"query","required":false,"description":"Number of items per page. Defaults to 50.","schema":{"type":"integer","default":50,"example":50}},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","example":1}},{"name":"filter[user_id]","in":"query","required":false,"description":"Filter by user identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"filter[status_id]","in":"query","required":false,"description":"Filter by status identifier.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"filter[start_time]","in":"query","required":false,"description":"Filter by start time.","schema":{"type":"string","format":"date-time","example":"2024-03-01T08:00:00Z"}},{"name":"filter[end_time]","in":"query","required":false,"description":"Filter by end time.","schema":{"type":"string","format":"date-time","example":"2024-03-01T17:00:00Z"}},{"name":"filter[is_synced]","in":"query","required":false,"description":"Filter by sync state with the external Tempus system.","schema":{"type":"boolean","example":true}},{"name":"sort","in":"query","required":false,"description":"Sort field. Allowed values: `start_time`, `end_time`, `created_at`.\nPrefix with `-` for descending order. Defaults to `-start_time`.\n","schema":{"type":"string","example":"-start_time"}}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTimePoint"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","user_id":"550e8400-e29b-41d4-a716-446655440002","status_id":"550e8400-e29b-41d4-a716-446655440003","location_id":"550e8400-e29b-41d4-a716-446655440010","start_time":"2026-07-07T10:07:39Z","end_time":"2026-07-07T12:00:00Z","sources":["mobile"],"triggers":["manual"],"meta_data":{"gpsLat":49.95,"gpsLong":6.133,"source":"api_v1","device_gps":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289},"location_check":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null}},"location":{"id":"550e8400-e29b-41d4-a716-446655440010","name":"HQ Luxembourg","latitude":49.6008,"longitude":6.133,"geofence_radius_m":150,"is_fixed_location":true},"device_gps":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289},"location_check":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null},"is_synced":true,"created_at":"2026-07-07T10:07:39Z","updated_at":"2026-07-07T12:00:00Z"}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/workTimes":{"get":{"tags":["Users"],"summary":"Get accumulated work times for the authenticated user (user)","operationId":"getUserWorkTimes","description":"Return the accumulated work-time totals for the authenticated user. When the\nPBX's Tempus app is sourced from Cockpit the totals are calculated locally;\notherwise they are fetched from the external Tempus system. If no data is\navailable, zeroed totals are returned.\n\nAll durations are formatted as `HH:MM:SS` strings. `min*` values represent the\nminimum (contractually required) duration for the corresponding period.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"workTimes":{"type":"object","properties":{"daily":{"type":"string","example":"08:00:00"},"minDaily":{"type":"string","example":"08:00:00"},"weekly":{"type":"string","example":"40:00:00"},"minWeekly":{"type":"string","example":"40:00:00"},"monthly":{"type":"string","example":"160:00:00"},"minMonthly":{"type":"string","example":"160:00:00"},"lunch":{"type":"string","example":"01:00:00"}}}}},"example":{"workTimes":{"daily":"08:00:00","minDaily":"08:00:00","weekly":"40:00:00","minWeekly":"40:00:00","monthly":"160:00:00","minMonthly":"160:00:00","lunch":"01:00:00"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/webhooks\/famulor\/post-call":{"post":{"tags":["Webhooks"],"summary":"Receive Famulor post-call events","operationId":"postWebhookFamulor","description":"Receives post-call payload from Famulor AI voice assistant after a call completes. Optionally validates the request via the X-Webhook-Secret header.","security":[],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"},{"name":"X-Webhook-Secret","in":"header","required":false,"schema":{"type":"string"},"description":"Optional webhook secret for request validation."}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","description":"Famulor post-call payload. The structure is defined by Famulor and may vary.","properties":{"assistant_id":{"type":"string","description":"The Famulor assistant (agent) ID."},"call_id":{"type":"string","description":"Unique identifier for the call."},"id":{"type":"string","description":"Alternative call identifier field."},"status":{"type":"string","description":"Status of the call (e.g. completed, missed)."},"type":{"type":"string","description":"Type of call."},"client_phone_number":{"type":"string","description":"Phone number of the client."},"assistant_phone_number":{"type":"string","description":"Phone number of the assistant."},"answered_by":{"type":["string","null"],"description":"Who answered the call."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the call was initiated."},"duration":{"type":"integer","description":"Call duration in seconds."},"total_cost":{"type":"number","description":"Total cost of the call."},"carrier_cost":{"type":"number","description":"Carrier cost portion of the total."},"transcript":{"type":["string","null"],"description":"Full transcript of the call."},"variables":{"type":["object","null"],"description":"Custom variables associated with the call."},"evaluation":{"type":["object","null"],"description":"Post-call evaluation data."},"recording_url":{"type":["string","null"],"description":"URL of the call recording."}},"additionalProperties":true},"example":{"assistant_id":"asst_abc123","call_id":"call_xyz789","status":"completed","type":"inbound","client_phone_number":"+32477123456","assistant_phone_number":"+32489654321","answered_by":"assistant","created_at":"2023-10-12T12:00:00Z","duration":120,"total_cost":0.05,"carrier_cost":0.02,"transcript":"Hello, how can I help you today?","variables":null,"evaluation":null,"recording_url":"https:\/\/storage.famulor.com\/recordings\/call_xyz789.mp3"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}},"example":{"success":true}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/v2\/test-latency":{"get":{"tags":["v2"],"summary":"Test API Latency","operationId":"getV2TestLatency","description":"A lightweight endpoint with no processing logic, used to measure API round-trip latency.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api","description":"v2 API server"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"example":{"message":"Test endpoint - no processing","timestamp":"2023-10-12T12:25:52.000000Z"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/v2\/change-status":{"post":{"tags":["v2"],"summary":"Change User Status","operationId":"postV2ChangeStatus","description":"Changes the authenticated user's status in the Tempus time-attendance system. Accepts either a Cockpit UUID or a Tempus mapping ID for the status.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api","description":"v2 API server"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["status_id"],"properties":{"status_id":{"type":"string","description":"The status UUID (Cockpit) or mapping ID (Tempus). If not a UUID, the system will attempt to resolve it via the Tempus mapping."},"location_id":{"type":["string","null"],"format":"uuid","description":"Optional location to associate with the status. Must reference a\nlocation of the caller's own PBX that is enabled for presence\nstatus.\n"},"sub_status_ids":{"type":["array","null"],"description":"Sub-status identifiers linked to the selected status. A single\nvalue unless the status allows multiselect; required when the\nstatus mandates a sub-status selection.\n","items":{"type":"string","format":"uuid"}},"sources":{"type":["array","null"],"items":{"type":"string"},"description":"Origin channels for the status change."},"triggers":{"type":["array","null"],"items":{"type":"string"},"description":"Triggers that initiated the status change."},"meta_data":{"type":["object","null"],"additionalProperties":true,"description":"Arbitrary metadata, stored verbatim on the time point. GPS\ncoordinates may be sent here (as `lat`\/`lng`,\n`latitude`\/`longitude`, or `gpsLat`\/`gpsLong`) or in `gpsData`.\nEither way they are normalised onto the time point as\n`device_gps` and compared with `location_id`, with the result\nexposed as `location_check`.\n\nCoordinates are recorded as sent and are never replaced by the\ncoordinates configured on `location_id`.\n"},"gpsData":{"type":["object","null"],"additionalProperties":true,"description":"The device's GPS fix, as clients have historically sent it. An\nalternative container to `meta_data`: both are accepted, both\nare stored, and sending both no longer discards this one.\n\nRead tolerantly. An unusable fix (half a pair, non-numeric, or\nout of range) does not fail the request: it is stored as sent\nand `location_check.reason` reports `no_device_gps`.\n"},"comment":{"type":["string","null"],"maxLength":255,"description":"Optional free-text comment."}}},"example":{"status_id":"550e8400-e29b-41d4-a716-446655440001","location_id":"550e8400-e29b-41d4-a716-446655440010","sub_status_ids":["550e8400-e29b-41d4-a716-446655440020"],"sources":["mobile"],"triggers":["manual"],"meta_data":{"app_version":"3.4.1"},"gpsData":{"gpsLat":49.95,"gpsLong":6.133,"accuracy":12.5,"gpsTimestamp":1783418859289},"comment":"Starting morning shift"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"ui":{"type":"object","properties":{"data":{"oneOf":[{"$ref":"#\/components\/schemas\/TempusTimePoint"},{"type":"array","maxItems":0,"items":{"type":"object"}}]}}},"workTimes":{"type":["object","null"],"description":"Always null on v2; poll the work-times endpoint instead."},"message":{"type":"string"}}},"example":{"ui":{"data":[]},"workTimes":null,"message":"Status changed successfully."}}}},"201":{"description":"A new time point was opened. `ui.data` is the created time point,\nincluding `device_gps` (the coordinates the client sent, stored as sent)\nand `location_check` (how they compare with the selected location's\nconfigured coordinates and geofence radius).\n","content":{"application\/json":{"schema":{"type":"object","properties":{"ui":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusTimePoint"}}},"workTimes":{"type":"null"}}},"example":{"ui":{"data":{"id":"550e8400-e29b-41d4-a716-446655440000","status_id":"550e8400-e29b-41d4-a716-446655440003","location_id":"550e8400-e29b-41d4-a716-446655440010","start_time":"2026-07-07T10:07:39.000000Z","end_time":null,"device_gps":{"latitude":49.95,"longitude":6.133,"accuracy_m":12.5,"captured_at":"2026-07-07T10:07:39+00:00","captured_at_raw":1783418859289},"location_check":{"location_id":"550e8400-e29b-41d4-a716-446655440010","location_latitude":49.6008,"location_longitude":6.133,"geofence_radius_m":150,"distance_m":38957,"within_geofence":false,"verdict":"mismatch","reason":null}}},"workTimes":null}}}},"409":{"description":"Another status change for this employee is already in progress and could\nnot be resolved. Retry once after a short delay.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"null"},"errors":{"type":"array","items":{"type":"string"}},"message":{"type":"string"}}},"example":{"data":null,"errors":["Another status change is already in progress. Please try again."],"message":"Status change failed."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/v2\/layout":{"get":{"tags":["v2"],"summary":"Get User Layout","operationId":"getV2Layout","description":"Returns the active status-changer layout for the authenticated user, including grid configuration, statuses, and substatuses.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api","description":"v2 API server"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"grid_size":{"type":"object","properties":{"rows":{"type":"integer"},"columns":{"type":"integer"}}},"statuses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object"},"metadata":{"type":"object","properties":{"availability":{"type":["string","null"]},"allow_multiselect":{"type":"boolean"},"substatus_selection_mandatory":{"type":"boolean"}}},"location_ids":{"type":"array","items":{"type":"string"}},"substatus_ids":{"type":"array","items":{"type":"string"}},"css_grid_area":{"type":"string"},"position":{"type":"object","properties":{"row":{"type":"integer"},"column":{"type":"integer"},"row_span":{"type":"integer"},"col_span":{"type":"integer"}}}}}},"substatuses":{"type":"object","additionalProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object"}}}}}},"example":{"id":"550e8400-e29b-41d4-a716-446655440010","name":"Default Layout","grid_size":{"rows":3,"columns":4},"statuses":[{"id":"550e8400-e29b-41d4-a716-446655440001","name":"Available","description":null,"style":{"background_color":"#00c853","font_color":"#ffffff","icon":"check"},"metadata":{"availability":"available","allow_multiselect":false,"substatus_selection_mandatory":false},"location_ids":[],"substatus_ids":[],"css_grid_area":"1\/1\/2\/2","position":{"row":1,"column":1,"row_span":1,"col_span":1}}],"substatuses":[]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/v2\/statuses":{"get":{"tags":["v2"],"summary":"Get v2 Statuses","operationId":"getV2Statuses","description":"Returns all Tempus statuses available for the authenticated user's PBX tenant, including style, metadata, and associated substatus and location IDs.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api","description":"v2 API server"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object","description":"Display style properties such as colors and icon."},"metadata":{"type":"object","properties":{"availability":{"type":["string","null"]},"allow_multiselect":{"type":"boolean"},"substatus_selection_mandatory":{"type":"boolean"}}},"location_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"substatus_ids":{"type":"array","items":{"type":"string","format":"uuid"}}}}},"example":[{"id":"550e8400-e29b-41d4-a716-446655440001","name":"Available","description":null,"style":{"background_color":"#00c853","font_color":"#ffffff","icon":"check"},"metadata":{"availability":"available","allow_multiselect":false,"substatus_selection_mandatory":false},"location_ids":[],"substatus_ids":[]},{"id":"550e8400-e29b-41d4-a716-446655440002","name":"Busy","description":null,"style":{"background_color":"#d32f2f","font_color":"#ffffff","icon":"phone"},"metadata":{"availability":"busy","allow_multiselect":false,"substatus_selection_mandatory":true},"location_ids":[],"substatus_ids":["660e8400-e29b-41d4-a716-446655440001"]}]}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/v2\/substatuses":{"get":{"tags":["v2"],"summary":"Get v2 Substatuses","operationId":"getV2Substatuses","description":"Returns all Tempus substatuses available for the authenticated user's PBX tenant, including style information.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Accept","in":"header","schema":{"type":"string"},"example":"application\/json"}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api","description":"v2 API server"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"0.0.0.0:8083"}},"Date":{"schema":{"type":"string","example":"Thu, 12 Oct 2023 12:25:52 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Access-Control-Allow-Origin":{"schema":{"type":"string","example":"*"}}},"content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object","description":"Display style properties such as colors and icon."}}}},"example":[{"id":"660e8400-e29b-41d4-a716-446655440001","name":"In Meeting","description":null,"style":{"background_color":"#ff6f00","font_color":"#ffffff","icon":"event"}},{"id":"660e8400-e29b-41d4-a716-446655440002","name":"On Break","description":null,"style":{"background_color":"#0288d1","font_color":"#ffffff","icon":"coffee"}}]}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}}},"\/cdrs":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (production)"},{"url":"https:\/\/staging-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (staging)"},{"url":"https:\/\/dev-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (development)"}],"get":{"tags":["CDRs"],"summary":"List call history (CDRs) (user, pbx)","operationId":"listCdrs","description":"Returns the paginated call history (call detail records) for the\nauthenticated principal, newest first. Results are scoped server-side to the\ncaller's PBX (and, for a user token, to the caller's own extension), so the\ncompany scope can never be supplied or overridden by the client.\n\nWith a PBX-owned API key the request spans the whole PBX by default. Pass\n`extension_id` or `extension` to narrow it to the calls made or received by a\nsingle user's extension. The value is validated against the authenticated PBX\nbefore use, and the pair is always re-derived server-side, so a mismatched\n`extension` \/ `extension_id` combination cannot widen the scope. With a user\npersonal access token both parameters are ignored: the query is always locked\nto the caller's own extension.\n\nAuthentication accepts either a user personal access token or a PBX-owned\nAPI key. A PBX API key must carry the `call-history` ability\/scope.\n\nRate-limited to 120 requests per minute per principal (user, PBX or IP);\nexceeding the limit returns `429 Too Many Requests`.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"extension_id","in":"query","required":false,"description":"Internal ID of the extension whose calls should be returned (the\nextension of the user who made or received the call). PBX API key only,\nand validated to belong to the authenticated PBX; a foreign extension\nreturns `403`. Takes precedence over `extension` when both are supplied.\nOmit to span every extension of the PBX. Ignored for user tokens.\n","schema":{"type":"integer","format":"int64","example":15754}},{"name":"extension","in":"query","required":false,"description":"Extension number of the user whose calls should be returned, as an\nalternative to `extension_id`. PBX API key only, and validated to belong\nto the authenticated PBX; a foreign extension returns `403`. Omit to span\nevery extension of the PBX. Ignored for user tokens.\n","schema":{"type":"string","example":"2039"}},{"name":"extras","in":"query","required":false,"description":"When `true`, each record includes the detailed `extras` payload (AI transcription availability and call-timeline data). Defaults to `false` for a lighter, faster response.","schema":{"type":"boolean","default":false,"example":false}},{"name":"call_type[]","in":"query","required":false,"description":"Filter by call type. Repeatable. One or more of the listed values.","schema":{"type":"array","items":{"type":"string","enum":["answered","missed","all","incoming","outgoing"]},"example":["incoming"]}},{"name":"start_time","in":"query","required":false,"description":"Start of the date\/time window (inclusive), in `YYYY-MM-DD HH:MM:SS` format.","schema":{"type":"string","example":"2025-01-01 00:00:00"}},{"name":"end_time","in":"query","required":false,"description":"End of the date\/time window (inclusive), in `YYYY-MM-DD HH:MM:SS` format.","schema":{"type":"string","example":"2026-01-12 23:50:59"}},{"name":"search","in":"query","required":false,"description":"Full-text search across the call records (names, numbers, and similar fields).","schema":{"type":"string","example":"Customer Support"}},{"name":"id","in":"query","required":false,"description":"When supplied, only records with a `cdr_id` greater than this value are returned. Use it to fetch only records newer than the last one you saw, for cheaper incremental polling.","schema":{"type":"integer","format":"int64","example":18457973}},{"name":"page","in":"query","required":false,"description":"Page number (1-based).","schema":{"type":"integer","minimum":1,"default":1,"example":1}},{"name":"page_size","in":"query","required":false,"description":"Number of records per page.","schema":{"type":"integer","minimum":1,"default":15,"example":5}},{"name":"remote_extension_number","in":"query","required":false,"description":"Filter to calls involving this remote party number or extension.","schema":{"type":"string","example":"2041"}}],"responses":{"200":{"description":"Paginated call history.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A single call-history row as returned by the call-history list endpoint. Each\nrecord summarises one call leg from the authenticated principal's perspective.\n","required":["cdr_id","type","is_missed_call","is_answered","date","start_time","end_time","duration","billsec","is_transfer_call","is_conference_call","is_recorded","notes_count","transcriptions_available","extras"],"properties":{"cdr_id":{"type":"string","description":"Unique identifier of the call detail record. Pass it to the detail and call-recording endpoints.","example":"24904193"},"pbx_user_id":{"type":["string","null"],"description":"Identifier of the PBX user the record belongs to.","example":"550e8400-e29b-41d4-a716-446655440010"},"pbx_profile_id":{"type":["string","null"],"description":"Profile identifier, when the call is attributed to a specific user profile.","example":null},"customer_pid":{"type":["string","null"],"description":"External customer identifier, when known.","example":null},"type":{"type":"string","enum":["INCOMING","OUTGOING"],"description":"Direction of the call relative to the PBX.","example":"INCOMING"},"is_missed_call":{"type":"boolean","description":"Whether the call was missed (never answered).","example":true},"is_answered":{"type":"boolean","description":"Whether the call was answered.","example":false},"remote_person_id":{"type":["string","null"],"description":"Identifier of the remote party (the other side of the call), when resolvable.","example":"550e8400-e29b-41d4-a716-446655440020"},"remote_person_name":{"type":["string","null"],"description":"Display name of the remote party.","example":"Customer Support"},"remote_person_number":{"type":["string","null"],"description":"Phone number or extension of the remote party.","example":"+12125550100"},"via_id":{"type":["string","null"],"description":"Identifier of the entity the call was routed via (call flow, queue, or number).","example":"550e8400-e29b-41d4-a716-446655440030"},"via_name":{"type":["string","null"],"description":"Display name of the routing entity.","example":"Main Line"},"via_number":{"type":["string","null"],"description":"Number of the routing entity.","example":"+12125550111"},"date":{"type":"string","format":"date","description":"Calendar date the call started, in `YYYY-MM-DD`.","example":"2026-01-12"},"start_time":{"type":"string","description":"When the call started, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:19"},"answer_time":{"type":["string","null"],"description":"When the call was answered, or null if it was never answered.","example":null},"end_time":{"type":"string","description":"When the call ended, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:25"},"duration":{"type":"integer","format":"int32","description":"Total call duration in seconds (from start to end).","example":6},"billsec":{"type":"integer","format":"int32","description":"Billable seconds (time the call was actually connected).","example":0},"is_transfer_call":{"type":"boolean","description":"Whether the call involved a transfer.","example":false},"is_conference_call":{"type":"boolean","description":"Whether the call was a conference.","example":false},"is_recorded":{"type":"boolean","description":"Whether a recording exists for this call.","example":false},"notes_count":{"type":"integer","format":"int32","description":"Number of notes attached to this call.","example":0},"transcriptions_available":{"type":"boolean","description":"Whether an AI transcription is available for this call.","example":false},"extras":{"type":"array","description":"Detailed extras (AI transcription and call-timeline data). Populated only when the request sets `extras=true`; otherwise an empty array.","items":{"type":"object","additionalProperties":true},"example":[]}}}},"pagination":{"type":"object","description":"Pagination metadata for the call-history list response.","properties":{"current_page":{"type":"integer","format":"int32","description":"The current page number.","example":1},"first_page_url":{"type":["string","null"],"description":"URL of the first page.","example":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=1"},"prev_page_url":{"type":["string","null"],"description":"URL of the previous page, or null on the first page.","example":null},"next_page_url":{"type":["string","null"],"description":"URL of the next page, or null on the last page.","example":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=2"},"last_page_url":{"type":["string","null"],"description":"URL of the last page.","example":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=103"},"last_page":{"type":"integer","format":"int32","description":"The number of the last page.","example":103},"per_page":{"type":"integer","format":"int32","description":"Number of records per page.","example":5},"total":{"type":"integer","format":"int32","description":"Total number of records across all pages.","example":515},"path":{"type":["string","null"],"description":"Base path of the paginated resource.","example":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs"}}},"cache_hit":{"type":"boolean","description":"Whether this response was served from the short-lived proxy cache.","example":false},"status":{"type":"boolean","description":"Whether the upstream request succeeded.","example":true},"message":{"type":"string","example":"CDRs retrieved successfully."}}},"example":{"data":[{"cdr_id":"24904193","pbx_user_id":"550e8400-e29b-41d4-a716-446655440010","pbx_profile_id":null,"customer_pid":null,"type":"INCOMING","is_missed_call":true,"is_answered":false,"remote_person_id":"550e8400-e29b-41d4-a716-446655440020","remote_person_name":"Customer Support","remote_person_number":"+12125550100","via_id":"550e8400-e29b-41d4-a716-446655440030","via_name":"Main Line","via_number":"+12125550111","date":"2026-01-12","start_time":"2026-01-12 15:50:19","answer_time":null,"end_time":"2026-01-12 15:50:25","duration":6,"billsec":0,"is_transfer_call":false,"is_conference_call":false,"is_recorded":false,"notes_count":0,"transcriptions_available":false,"extras":[]},{"cdr_id":"24890011","pbx_user_id":"550e8400-e29b-41d4-a716-446655440010","pbx_profile_id":null,"customer_pid":null,"type":"OUTGOING","is_missed_call":false,"is_answered":true,"remote_person_id":"550e8400-e29b-41d4-a716-446655440021","remote_person_name":"Sales Team","remote_person_number":"+12125550101","via_id":"550e8400-e29b-41d4-a716-446655440030","via_name":"Main Line","via_number":"+12125550111","date":"2026-01-05","start_time":"2026-01-05 15:33:09","answer_time":"2026-01-05 15:33:14","end_time":"2026-01-05 15:38:02","duration":293,"billsec":293,"is_transfer_call":false,"is_conference_call":false,"is_recorded":true,"notes_count":0,"transcriptions_available":true,"extras":[]}],"pagination":{"current_page":1,"first_page_url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=1","prev_page_url":null,"next_page_url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=2","last_page_url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs?page=103","last_page":103,"per_page":5,"total":515,"path":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility\/cdrs"},"cache_hit":false,"status":true,"message":"CDRs retrieved successfully."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Either the presented PBX API key does not carry the required\n`call-history` ability\/scope, or the requested `extension_id` \/\n`extension` does not belong to the authenticated PBX. A user token whose\naccount has no extension assigned is rejected here as well.\n"},"429":{"description":"Too many requests. The endpoint is rate-limited to 120 requests per minute per principal. Retry after the window indicated by the `Retry-After` response header."}}}},"\/cdrs\/detail\/{id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (production)"},{"url":"https:\/\/staging-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (staging)"},{"url":"https:\/\/dev-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (development)"}],"get":{"tags":["CDRs"],"summary":"Get call detail by ID (user, pbx)","operationId":"getCdrDetail","description":"Returns the full detail of a single call, including each receiving leg, the\ncall-flow timeline, recording-file references, notes, and AI transcription\nresults. Scoped server-side to the caller's PBX.\n\nAuthentication accepts either a user personal access token or a PBX-owned\nAPI key. A PBX API key must carry the `call-history` ability\/scope.\n\nRate-limited to 120 requests per minute per principal.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"description":"The `cdr_id` of the call, as returned by the call-history list.","schema":{"type":"integer","format":"int64","example":24904193}}],"responses":{"200":{"description":"The call detail.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Full detail of a single call, including every receiving leg, the call-flow\ntimeline, recording references, notes, and AI transcription results.\n","required":["id","type","date","start_time","end_time","duration","billsec","caller","receivers"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the call detail record.","example":24904193},"company_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) the call belongs to.","example":"550e8400-e29b-41d4-a716-446655440000"},"type":{"type":"string","enum":["INCOMING","OUTGOING"],"description":"Direction of the call.","example":"OUTGOING"},"date":{"type":"string","format":"date","description":"Calendar date the call started.","example":"2026-01-12"},"start_time":{"type":"string","description":"When the call started, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:19"},"answer_time":{"type":["string","null"],"description":"When the call was answered, or null if never answered.","example":null},"end_time":{"type":"string","description":"When the call ended, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:25"},"duration":{"type":"integer","format":"int32","description":"Total duration in seconds.","example":6},"billsec":{"type":"integer","format":"int32","description":"Billable seconds.","example":0},"is_transfer_call":{"type":"boolean","example":false},"is_internal":{"type":"boolean","description":"Whether both parties are internal to the PBX.","example":true},"is_conference_call":{"type":"boolean","example":false},"conference":{"type":"array","description":"Conference participant legs, when the call was a conference.","items":{"type":"object","additionalProperties":true},"example":[]},"is_recording_file_exists":{"type":"boolean","description":"Whether a recording file exists for this call.","example":false},"recording_file":{"type":"object","description":"A call-recording file reference. The recording can only be downloaded with a\nbearer token (see the call-recording endpoint); the `path` and `download_url`\nare populated only when a recording exists.\n","properties":{"name":{"type":"string","description":"File name of the recording, or an empty string when none exists.","example":""},"path":{"type":["string","null"],"description":"Storage path of the recording, used as the `path` query parameter on the call-recording endpoint.","example":null},"download_url":{"type":["string","null"],"description":"Direct download URL of the recording, when available.","example":null},"hint":{"type":"string","description":"Human-readable note describing which part of the call this recording covers and how to download it.","example":"This recording file is for the entire call, including both caller and callee recordings. You can only download it using your bearer token."}}},"recording_file_path_caller":{"type":"object","description":"A call-recording file reference. The recording can only be downloaded with a\nbearer token (see the call-recording endpoint); the `path` and `download_url`\nare populated only when a recording exists.\n","properties":{"name":{"type":"string","description":"File name of the recording, or an empty string when none exists.","example":""},"path":{"type":["string","null"],"description":"Storage path of the recording, used as the `path` query parameter on the call-recording endpoint.","example":null},"download_url":{"type":["string","null"],"description":"Direct download URL of the recording, when available.","example":null},"hint":{"type":"string","description":"Human-readable note describing which part of the call this recording covers and how to download it.","example":"This recording file is for the entire call, including both caller and callee recordings. You can only download it using your bearer token."}}},"recording_file_path_callee":{"type":"object","description":"A call-recording file reference. The recording can only be downloaded with a\nbearer token (see the call-recording endpoint); the `path` and `download_url`\nare populated only when a recording exists.\n","properties":{"name":{"type":"string","description":"File name of the recording, or an empty string when none exists.","example":""},"path":{"type":["string","null"],"description":"Storage path of the recording, used as the `path` query parameter on the call-recording endpoint.","example":null},"download_url":{"type":["string","null"],"description":"Direct download URL of the recording, when available.","example":null},"hint":{"type":"string","description":"Human-readable note describing which part of the call this recording covers and how to download it.","example":"This recording file is for the entire call, including both caller and callee recordings. You can only download it using your bearer token."}}},"caller":{"type":"object","description":"The originating party.","properties":{"id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440041"},"name":{"type":"string","example":"Customer Support"},"number":{"type":"string","example":"2041"}}},"receivers":{"type":"array","description":"Every receiving leg that was rung for this call.","items":{"type":"object","description":"One receiving leg of a call (a destination that was rung), with its own timing and routing.","properties":{"id":{"type":["string","null"],"description":"Identifier of the receiver (user, extension, or external party).","example":"550e8400-e29b-41d4-a716-446655440040"},"status":{"type":"string","enum":["TRIGGERED","RINGING","ANSWERED","MISSED","BUSY","FAILED"],"description":"Outcome for this receiving leg.","example":"TRIGGERED"},"name":{"type":"string","description":"Display name of the receiver, or an empty string when unknown.","example":"Sales Team"},"number":{"type":"string","description":"Phone number or extension of the receiver.","example":"2039"},"start_time":{"type":"string","description":"When this leg started ringing, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:19"},"answer_time":{"type":["string","null"],"description":"When this leg was answered, or null if never answered.","example":"2026-01-12 15:50:19"},"end_time":{"type":"string","description":"When this leg ended, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:25"},"duration":{"type":"integer","format":"int32","description":"Duration of this leg in seconds.","example":6},"billsec":{"type":"integer","format":"int32","description":"Billable seconds for this leg.","example":6},"via_id":{"type":["string","null"],"description":"Identifier of the entity this leg was routed via.","example":"550e8400-e29b-41d4-a716-446655440030"},"via_name":{"type":["string","null"],"description":"Display name of the routing entity.","example":"Main Line"},"via_number":{"type":["string","null"],"description":"Number of the routing entity.","example":"+12125550111"},"via_type":{"type":["string","null"],"enum":["CALL_FLOW","QUEUE","TWINNING","IVR",null],"description":"How this leg was reached, or null when not applicable.","example":"CALL_FLOW"}}}},"call_flow":{"type":"array","description":"Human-readable, ordered timeline of what happened during the call.","items":{"type":"object","properties":{"color":{"type":"string","description":"UI severity hint for the timeline entry.","enum":["info","secondary","success","warning","danger"],"example":"info"},"text":{"type":"string","description":"Primary timeline message.","example":"OUTGOING - Call started by Customer Support (2041)"},"sub_text":{"type":["string","null"],"description":"Secondary timeline detail.","example":null},"time":{"type":"string","description":"When the timeline entry occurred, in `YYYY-MM-DD HH:MM:SS`.","example":"2026-01-12 15:50:19"}}}},"notes":{"type":"array","description":"Notes attached to the call.","items":{"type":"object","additionalProperties":true},"example":[]},"transcriptions":{"type":["object","null"],"description":"AI transcription result, or null when none is available.","additionalProperties":true,"example":null},"ai_processing_errors":{"type":"array","description":"Errors raised while AI-processing the call, if any.","items":{"type":"object","additionalProperties":true},"example":[]}}},"status":{"type":"boolean","example":true},"message":{"type":"string","example":"CDRs"}}},"example":{"data":{"id":24904193,"company_id":"550e8400-e29b-41d4-a716-446655440000","type":"OUTGOING","date":"2026-01-12","start_time":"2026-01-12 15:50:19","answer_time":null,"end_time":"2026-01-12 15:50:25","duration":6,"billsec":0,"is_transfer_call":false,"is_internal":true,"is_conference_call":false,"conference":[],"is_recording_file_exists":false,"recording_file":{"name":"","path":null,"download_url":null,"hint":"This recording file is for the entire call, including both caller and callee recordings. You can only download it using your bearer token."},"recording_file_path_caller":{"name":"","path":null,"download_url":null,"hint":"This recording file is for the caller part of the call. You can only download it using your bearer token."},"recording_file_path_callee":{"name":"","path":null,"download_url":null,"hint":"This recording file is for the callee part of the call. You can only download it using your bearer token."},"caller":{"id":"550e8400-e29b-41d4-a716-446655440041","name":"Customer Support","number":"2041"},"receivers":[{"id":"550e8400-e29b-41d4-a716-446655440042","status":"TRIGGERED","name":"Sales Team","number":"2039","start_time":"2026-01-12 15:50:19","answer_time":"2026-01-12 15:50:19","end_time":"2026-01-12 15:50:25","duration":6,"billsec":6,"via_id":"550e8400-e29b-41d4-a716-446655440041","via_name":"Customer Support","via_number":"2041","via_type":"CALL_FLOW"},{"id":"550e8400-e29b-41d4-a716-446655440043","status":"MISSED","name":"","number":"+12125550100","start_time":"2026-01-12 15:50:21","answer_time":null,"end_time":"2026-01-12 15:50:25","duration":6,"billsec":0,"via_id":"550e8400-e29b-41d4-a716-446655440041","via_name":"Customer Support","via_number":"2041","via_type":"TWINNING"}],"call_flow":[{"color":"info","text":"OUTGOING - Call started by Customer Support (2041)","sub_text":null,"time":"2026-01-12 15:50:19"},{"color":"secondary","text":"Triggered Sales Team (2039)","sub_text":"Via [CALL_FLOW] - Customer Support (2041)","time":"2026-01-12 15:50:19"},{"color":"danger","text":"Missed by Sales Team (2039)","sub_text":"Via Customer Support (2041)","time":"2026-01-12 15:50:20"},{"color":"info","text":"Call Finished","sub_text":null,"time":"2026-01-12 15:50:25"}],"notes":[],"transcriptions":null,"ai_processing_errors":[]},"status":true,"message":"CDRs"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The presented PBX API key does not carry the required `call-history` ability\/scope."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"429":{"description":"Too many requests. Rate-limited to 120 requests per minute per principal."}}}},"\/call-recording":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (production)"},{"url":"https:\/\/staging-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (staging)"},{"url":"https:\/\/dev-cockpit.voxbi.com\/api\/v1\/cdrs-utility","description":"CDR utility API server (development)"}],"get":{"tags":["CDRs"],"summary":"Download a call recording (user, pbx)","operationId":"getCdrCallRecording","description":"Streams the audio recording for a call. By default the recording for the\ngiven call `id` is returned. To fetch a specific recording variant (caller\nleg, callee leg, or the combined file), pass its `path` (obtained from the\n`recording_file*` references on the call-detail or, in the list, when\n`extras=true`).\n\nAuthentication accepts either a user personal access token or a PBX-owned\nAPI key. A PBX API key must carry the `call-history` ability\/scope.\n\nRate-limited to 120 requests per minute per principal.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"description":"The `cdr_id` of the call whose recording to download.","schema":{"type":"integer","format":"int64","example":24624794}},{"name":"path","in":"query","required":false,"description":"Specific recording-file path to download (the `path` value from a\n`recording_file`, `recording_file_path_caller`, or\n`recording_file_path_callee` reference). Omit to download the default\nrecording for the call.\n","schema":{"type":"string","example":"recordings\/2026\/01\/12\/24624794-full.wav"}}],"responses":{"200":{"description":"The recording audio stream.","content":{"audio\/wav":{"schema":{"type":"string","format":"binary"}},"audio\/mpeg":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The presented PBX API key does not carry the required `call-history` ability\/scope."},"404":{"description":"No recording exists for the given call or path."},"429":{"description":"Too many requests. Rate-limited to 120 requests per minute per principal."}}}},"\/AndroidNfc\/getUser":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusInternal"],"summary":"Get user by NFC badge","operationId":"getTempusAndroidNfc","description":"Returns a paginated list of tempus android nfc. Use the standard `search`, `sort`, `page`,\nand `perPage` query parameters; use `filter[key]=value` to narrow the result set.\nMulti-tenant scoping is enforced. Requires a PBX API-key token carrying the `terminals` ability.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"currentStatus":{"type":["object","null"],"description":"The user's ongoing timepoint status (tempus StatusResource) with timepoint_id, start_time, created_at and timepoint_location appended. Null when the user has no ongoing timepoint.\n"},"userInfo":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"bearerToken":{"type":"string","description":"Freshly issued Sanctum token for the badge session."},"displayName":{"type":["string","null"]}}},"layout":{"type":["object","null"],"description":"Terminal layout (tempus LayoutResource) with options, layout and preview_url. Null when no layout is configured.\n"}}},"example":{"currentStatus":{"id":"550e8400-e29b-41d4-a716-446655440000","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440001","name":"Working","icon":"la la-briefcase","fontcolor":"#ffffff","backgroundcolor":"#2e7d32","payable":true,"availability":"available","sub_statuses":[],"timepoint_id":"550e8400-e29b-41d4-a716-446655440020","start_time":"2026-07-16T08:00:00.000000Z","created_at":"2026-07-16T08:00:00.000000Z","timepoint_location":"550e8400-e29b-41d4-a716-446655440030"},"userInfo":{"id":"550e8400-e29b-41d4-a716-446655440002","bearerToken":"42|aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789AbCd","displayName":"Jane Smith"},"layout":{"options":{"geoEnable":true,"geoForce":false,"postAction":false,"updateTimer":5000},"layout":{"id":"550e8400-e29b-41d4-a716-446655440040","name":"Default Tempus","type":"default","tl_layouts_statuses":[]},"preview_url":"https:\/\/cockpit.voxbi.com\/layout-preview\/550e8400-e29b-41d4-a716-446655440040"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}},"post":{"tags":["TempusInternal"],"summary":"Log a terminal NFC event","operationId":"postTempusAndroidNfc","description":"Creates a new tempus android nfc. Validation rules and required fields are defined in the\nrequest body schema below. Requires a PBX API-key token carrying the `terminals` ability.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"badge_id":{"type":"string","example":"BADGE123"},"terminal_id":{"type":"string","example":"TERM01"},"timestamp":{"type":"string","format":"date-time","example":"2024-01-15T08:30:00Z"}}},"example":{"badge_id":"BADGE123","terminal_id":"TERM01","timestamp":"2024-01-15T08:30:00Z"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"created":{"type":"string","description":"Creation timestamp, formatted `Y-m-d H:i:s`."}}}}},"example":{"success":true,"message":"Terminal log created successfully","data":{"id":"550e8400-e29b-41d4-a716-446655440050","created":"2026-07-16 09:15:42"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/terminal\/{mac_address}\/badge":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusInternal"],"summary":"Get tablet session (grid layout format)","operationId":"postTempusTerminalBadge","description":"Returns the tablet session for a scanned badge: current status, work-time\nsummary, layout and terminal location. Requires a PBX API-key token with the\n`terminals` ability.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"mac_address","in":"path","required":true,"description":"The tablet's MAC address (any format; case-insensitive).","schema":{"type":"string"},"example":"001122334455"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["badge_identifier"],"properties":{"badge_identifier":{"type":"string","description":"The scanned NFC badge identifier."}}},"example":{"badge_identifier":"BADGE-0001"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"current_status":{"type":["object","null"],"description":"The status the user is currently in; null when there is no ongoing timepoint.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"style":{"type":"object"},"metadata":{"type":"object","properties":{"availability":{"type":["string","null"]},"allow_multiselect":{"type":"boolean"},"substatus_selection_mandatory":{"type":"boolean"}}},"location_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"substatus_ids":{"type":"array","items":{"type":"string","format":"uuid"}}}},"user_info":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"bearer_token":{"type":"string","description":"Freshly issued Sanctum token for the badge session."},"display_name":{"type":["string","null"]}}},"work_times":{"type":"object","description":"Current-day work-time summary (HH:MM:SS).","properties":{"daily":{"type":"string"},"min_daily":{"type":"string"},"weekly":{"type":"string"},"min_weekly":{"type":"string"},"monthly":{"type":"string"},"min_monthly":{"type":"string"},"lunch":{"type":"string"}}},"layout":{"type":["object","null"],"description":"The assigned layout; null when no active layout is configured.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"grid_size":{"type":"object","properties":{"rows":{"type":"integer"},"columns":{"type":"integer"}}},"statuses":{"type":"array","items":{"type":"object"}},"substatuses":{"type":"object"}}},"location":{"type":["object","null"],"description":"The terminal's location; null when it has none or no terminal matched.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]}}}}},"example":{"current_status":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Working","description":"Regular working time","style":{"icon_class":"la la-briefcase","bg_color":"#2e7d32","font_color":"#ffffff"},"metadata":{"availability":"available","allow_multiselect":false,"substatus_selection_mandatory":false},"location_ids":[],"substatus_ids":[]},"user_info":{"id":"550e8400-e29b-41d4-a716-446655440002","bearer_token":"42|aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789AbCd","display_name":"Jane Smith"},"work_times":{"daily":"07:30:00","min_daily":"08:00:00","weekly":"37:30:00","min_weekly":"40:00:00","monthly":"150:00:00","min_monthly":"160:00:00","lunch":"00:30:00"},"layout":{"id":"550e8400-e29b-41d4-a716-446655440040","name":"Default Tempus","grid_size":{"rows":3,"columns":3},"statuses":[],"substatuses":[]},"location":{"id":"550e8400-e29b-41d4-a716-446655440030","name":"Head Office","description":"Main office location"}}}}},"400":{"description":"Missing required field (badge_identifier).","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}},"example":{"error":"Missing required field: badge_identifier"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The matched terminal exists but is not active. No session is returned.","content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}},"example":{"error":"Terminal exists but is not active"}}}}}}},"\/TimeLogger\/getBadge":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusInternal"],"summary":"Get badge data (TimeLogger)","operationId":"getTempusTimeLogger","description":"Returns a paginated list of tempus time logger. Use the standard `search`, `sort`, `page`,\nand `perPage` query parameters; use `filter[key]=value` to narrow the result set.\nMulti-tenant scoping is enforced. Requires a PBX API-key token carrying the `terminals` ability.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"full_name":{"type":["string","null"]},"extension_number":{"type":["string","null"],"description":"The user's extension number, or null when none is assigned."},"email":{"type":["string","null"]},"active":{"type":"boolean"}}},"auth_info":{"type":"object","properties":{"bearerToken":{"type":"string","description":"Freshly issued Sanctum token for the badge session."},"pbx_id":{"type":"string","format":"uuid"}}}}},"example":{"user":{"id":"550e8400-e29b-41d4-a716-446655440002","full_name":"Jane Smith","extension_number":"1042","email":"jane.smith@example.com","active":true},"auth_info":{"bearerToken":"43|ZyXwVuTsRqPoNmLkJiHgFeDcBa9876543210ZyXw","pbx_id":"550e8400-e29b-41d4-a716-446655440001"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}}}},"post":{"tags":["TempusInternal"],"summary":"Submit badge data (TimeLogger)","operationId":"postTempusTimeLogger","description":"Creates a new tempus time logger. Validation rules and required fields are defined in the\nrequest body schema below. Requires a PBX API-key token carrying the `terminals` ability.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"badge_id":{"type":"string","example":"BADGE123"},"terminal_id":{"type":"string","example":"TERM01"}}},"example":{"badge_id":"BADGE123","terminal_id":"TERM01"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"full_name":{"type":["string","null"]},"extension_number":{"type":["string","null"],"description":"The user's extension number, or null when none is assigned."},"email":{"type":["string","null"]},"active":{"type":"boolean"}}},"auth_info":{"type":"object","properties":{"bearerToken":{"type":"string","description":"Freshly issued Sanctum token for the badge session."},"pbx_id":{"type":"string","format":"uuid"}}}}},"example":{"user":{"id":"550e8400-e29b-41d4-a716-446655440002","full_name":"Jane Smith","extension_number":"1042","email":"jane.smith@example.com","active":true},"auth_info":{"bearerToken":"43|ZyXwVuTsRqPoNmLkJiHgFeDcBa9876543210ZyXw","pbx_id":"550e8400-e29b-41d4-a716-446655440001"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/recurring-transactions\/preview-next-run":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusInternal"],"summary":"Preview the next run of a recurring transaction","operationId":"postTempusRecurringTransactionPreviewNextRun","description":"Computes the next materialisation date for a given frequency without creating a\ntemplate. Server-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["frequency"],"properties":{"frequency":{"type":"string","enum":["monthly_start","yearly_start"]},"run_once":{"type":"boolean"},"from":{"type":"string","format":"date","description":"Optional anchor date. Defaults to today."}}},"example":{"frequency":"monthly_start","from":"2026-06-15"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"next_run_at":{"type":"string","format":"date-time"},"next_run_at_human":{"type":"string"},"timezone":{"type":"string"}}},"example":{"next_run_at":"2026-07-01T00:00:00+00:00","next_run_at_human":"July 1, 2026","timezone":"Europe\/Luxembourg"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/recurring-transactions":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusInternal"],"summary":"List recurring transactions","operationId":"listTempusRecurringTransactions","description":"Returns a paginated list of recurring transaction templates for the authenticated PBX,\nordered by creation date descending. Server-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"employee_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter by Tempus employee."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","paused","completed","failed"]}},{"name":"frequency","in":"query","required":false,"schema":{"type":"string","enum":["monthly_start","yearly_start"]}},{"name":"run_once","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":25,"minimum":1,"maximum":100}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}}}},"post":{"tags":["TempusInternal"],"summary":"Create a recurring transaction","operationId":"createTempusRecurringTransaction","description":"Creates a recurring transaction template for the authenticated PBX. The template is\nactivated immediately and its first `next_run_at` is computed from the frequency.\nThe PBX is resolved from the API key, so `pbx_id` is never part of the request body.\nServer-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["employee_id","type","amount","tr_type","frequency"],"properties":{"employee_id":{"type":"string","format":"uuid","description":"Must be an active Tempus employee of the authenticated PBX."},"type":{"type":"string"},"sub_type":{"type":["string","null"]},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Must be an absence type of the authenticated PBX, when supplied."},"amount":{"type":"number","format":"float","description":"Greater than zero."},"tr_type":{"type":"string","enum":["credit","debit"]},"note":{"type":["string","null"],"maxLength":65535},"frequency":{"type":"string","enum":["monthly_start","yearly_start"]},"run_once":{"type":"boolean"}}},"example":{"employee_id":"550e8400-e29b-41d4-a716-446655440002","type":"bonus","amount":8,"tr_type":"credit","frequency":"monthly_start","run_once":false,"note":"Monthly meal allowance"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/recurring-transactions\/{id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusInternal"],"summary":"Get a recurring transaction","operationId":"getTempusRecurringTransaction","description":"Returns a single recurring transaction template. Server-to-server only (PBX API key).","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"patch":{"tags":["TempusInternal"],"summary":"Update a recurring transaction","operationId":"patchTempusRecurringTransaction","description":"Updates the mutable fields of a recurring transaction template. Only `amount`, `tr_type`,\n`note`, `frequency` and `run_once` can be changed; `employee_id`, `type`, `sub_type`,\n`absence_type_id` and `pbx_id` are fixed at creation. Changing `frequency` recomputes the\nnext run. Server-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","properties":{"amount":{"type":"number","format":"float","description":"Greater than zero."},"tr_type":{"type":"string","enum":["credit","debit"]},"note":{"type":["string","null"],"maxLength":65535},"frequency":{"type":"string","enum":["monthly_start","yearly_start"]},"run_once":{"type":"boolean"}}},"example":{"amount":10,"note":"Updated allowance"}}}},"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["TempusInternal"],"summary":"Delete a recurring transaction","operationId":"deleteTempusRecurringTransaction","description":"Soft-deletes a recurring transaction template. Server-to-server only (PBX API key).","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"204":{"description":"No Content"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/recurring-transactions\/{id}\/pause":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusInternal"],"summary":"Pause a recurring transaction","operationId":"postTempusRecurringTransactionPause","description":"Sets the template status to `paused`. Server-to-server only (PBX API key).","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/recurring-transactions\/{id}\/resume":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusInternal"],"summary":"Resume a recurring transaction","operationId":"postTempusRecurringTransactionResume","description":"Sets the template status back to `active`, clears any failure reason, and re-anchors\n`next_run_at` to the next valid occurrence when it is null or in the past.\nServer-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/recurring-transactions\/{id}\/run-now":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusInternal"],"summary":"Run a recurring transaction now","operationId":"postTempusRecurringTransactionRunNow","description":"Materialises the template immediately (out of schedule). The template must be `active`.\nThe HTTP response is `200` even when the individual run is skipped or fails; read\n`run.status` for the per-run outcome. Server-to-server only (PBX API key).\n","security":[{"PbxApiKey":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK. The run was attempted; inspect `run.status` for the outcome.","content":{"application\/json":{"schema":{"type":"object","properties":{"run":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"reason":{"type":["string","null"]},"tempus_transaction_id":{"type":["string","null"]},"ran_at":{"type":["string","null"],"format":"date-time"}}},"template":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique recurring transaction template identifier.","example":"550e8400-e29b-41d4-a716-446655440000"},"pbx_id":{"type":"string","format":"uuid","description":"PBX tenant the template belongs to.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_id":{"type":"string","format":"uuid","description":"Tempus employee the materialised transactions are booked against.","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","description":"Transaction type key.","example":"bonus"},"sub_type":{"type":["string","null"],"description":"Optional sub-type key.","example":"annual"},"absence_type_id":{"type":["string","null"],"format":"uuid","description":"Linked absence type, when the transaction credits or debits an absence balance.","example":null},"amount":{"type":"number","format":"float","description":"Amount applied on each run. Always greater than zero.","example":8},"tr_type":{"type":"string","enum":["credit","debit"],"description":"Whether each run credits or debits the balance.","example":"credit"},"note":{"type":["string","null"],"description":"Free-text note carried onto each materialised transaction.","example":"Monthly meal allowance"},"frequency":{"type":"string","enum":["monthly_start","yearly_start"],"description":"When the template materialises a transaction.","example":"monthly_start"},"run_once":{"type":"boolean","description":"When true the template runs a single time and then completes.","example":false},"status":{"type":"string","enum":["active","paused","completed","failed"],"description":"Lifecycle status of the template.","example":"active"},"failure_reason":{"type":["string","null"],"description":"Populated when the last run failed.","example":null},"next_run_at":{"type":["string","null"],"format":"date-time","description":"Next scheduled materialisation, in ISO 8601.","example":"2026-07-01T00:00:00+00:00"},"last_run_at":{"type":["string","null"],"format":"date-time","description":"Last materialisation timestamp, in ISO 8601.","example":null},"last_transaction_id":{"type":["string","null"],"description":"Identifier of the most recently materialised Tempus transaction.","example":null},"created_by_user_id":{"type":["string","null"],"description":"User who created the template. Always null when created through the API key flow.","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-06-01T08:29:07+00:00"}}}}},"example":{"run":{"id":"550e8400-e29b-41d4-a716-446655440010","status":"succeeded","reason":null,"tempus_transaction_id":"550e8400-e29b-41d4-a716-446655440011","ran_at":"2026-06-30T09:15:00+00:00"},"template":{"id":"550e8400-e29b-41d4-a716-446655440000","status":"active"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated principal is not allowed to manage recurring transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You are not authorised to manage recurring transactions."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"The recurring transaction is not active and cannot be run.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"This recurring transaction is not active."}}}}}}},"\/{pbx_id}\/users":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusEmployees"],"summary":"List Tempus employees for the tenant (user)","operationId":"tempusListUsers","description":"Returns a paginated list of Tempus employees (time-and-attendance records) belonging to the PBX tenant identified by `pbx_id`. Each item is serialized by the `TempusUserResource` and combines the `TempusEmployee` record with data resolved from its linked Voxbi user account and first telephony extension. The authenticated user must have an associated employee record and must belong to the requested PBX, otherwise the request is rejected with 403. Results may be filtered by department via `filter[group_id]` (matched through employee contracts) and are sorted by id by default.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[group_id]","in":"query","required":false,"description":"Comma-separated list of department (group) UUIDs to restrict results to. Employees are matched through their contracts' department assignment. Each value must be a valid UUID or the request is rejected with 422.\n","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20}],"responses":{"200":{"description":"Paginated list of Tempus employees.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusUser"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record, or does not belong to the requested PBX tenant.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/absences":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusAbsences"],"summary":"List absences for the tenant (user)","operationId":"tempusListAbsences","description":"Returns a paginated list of absence transactions for the PBX tenant. Each item is a `TempusTransaction` ledger row of type absence, illness, special, or legal holiday.\n\nOnly days actually taken are returned. Ledger rows that ADD days to a balance are excluded, because they are not time off: every credit row (`tr_type: credit`), including credits carrying no `sub_type` at all; the entitlement and carry-over sub-types (`computed_legal`, `computed_ph_on_day_off`, `computed_ph_on_same_day`, `computed_age`, `computed_experience`, `computed_company_day_off`, `computed_company_day_off_extra`, `legacy_custom`, `rollover`, `converted_balance`), which can be stored as debits and so are excluded by sub-type as well; `special_holiday` reversal rows; and `removal` give-backs. Granted days are reported by `GET \/{pbx_id}\/user\/{employee_id}\/calendar` instead. Passing one of the excluded values as `filter[sub_type]` therefore returns an empty list.\n\nBy default the result covers every employee in the caller's active-contract company (a team holiday overview). `filter[employee_id]` and `filter[department_id]` narrow the set within that company. Filtering, sorting, and includes are powered by Spatie Query Builder.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[status]","in":"query","required":false,"description":"Filter by transaction status (exact match).","schema":{"type":"string"},"example":"accepted"},{"name":"filter[type]","in":"query","required":false,"description":"Filter by transaction type (exact match).","schema":{"type":"string"},"example":"legal"},{"name":"filter[sub_type]","in":"query","required":false,"description":"Filter by absence sub-type code (exact match). Must be a valid `TempusAbsenceType` code or the request is rejected with 422.\n","schema":{"type":"string"},"example":"paid_leave"},{"name":"filter[from]","in":"query","required":false,"description":"Return absences whose start date is on or after this date.","schema":{"type":"string","format":"date"},"example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Return absences whose end date is on or before this date.","schema":{"type":"string","format":"date"},"example":"2026-12-31"},{"name":"filter[employee_id]","in":"query","required":false,"description":"Comma-separated list of employee UUIDs to restrict results to. Requires permission to view other employees' absences.\n","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[department_id]","in":"query","required":false,"description":"Comma-separated list of Tempus department UUIDs to restrict results to. Requires permission to view other employees' absences.\n","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"sort","in":"query","required":false,"description":"Sort field. Allowed: start_date, end_date, created_at. Prefix with - for descending.","schema":{"type":"string"},"example":"-start_date"},{"name":"include","in":"query","required":false,"description":"Comma-separated related resources to include. Allowed: employee, requester.","schema":{"type":"string"},"example":"employee"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":2000,"default":15},"example":15}],"responses":{"200":{"description":"Paginated list of absence transactions.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/absences":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusAbsences"],"summary":"List absences for a specific employee (user)","operationId":"tempusListUserAbsences","description":"Returns a paginated list of absence transactions for a single employee. Each item is a `TempusTransaction` ledger row of type absence, illness, special, or legal holiday.\n\nOnly days actually taken are returned. Ledger rows that ADD days to a balance are excluded, because they are not time off: every credit row (`tr_type: credit`), including credits carrying no `sub_type` at all; the entitlement and carry-over sub-types (`computed_legal`, `computed_ph_on_day_off`, `computed_ph_on_same_day`, `computed_age`, `computed_experience`, `computed_company_day_off`, `computed_company_day_off_extra`, `legacy_custom`, `rollover`, `converted_balance`), which can be stored as debits and so are excluded by sub-type as well; `special_holiday` reversal rows; and `removal` give-backs. Granted days are reported by `GET \/{pbx_id}\/user\/{employee_id}\/calendar` instead. Passing one of the excluded values as `filter[sub_type]` therefore returns an empty list.\n\nThe caller may always view their own absences; viewing another employee's absences requires the appropriate validator scope, otherwise the request is rejected with 403. Filtering and sorting are powered by Spatie Query Builder.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose absences are requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[status]","in":"query","required":false,"description":"Filter by transaction status (exact match).","schema":{"type":"string"},"example":"accepted"},{"name":"filter[type]","in":"query","required":false,"description":"Filter by transaction type (exact match).","schema":{"type":"string"},"example":"legal"},{"name":"filter[sub_type]","in":"query","required":false,"description":"Filter by absence sub-type code (exact match). Must be a valid `TempusAbsenceType` code or the request is rejected with 422.\n","schema":{"type":"string"},"example":"paid_leave"},{"name":"filter[from]","in":"query","required":false,"description":"Return absences whose start date is on or after this date.","schema":{"type":"string","format":"date"},"example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Return absences whose end date is on or before this date.","schema":{"type":"string","format":"date"},"example":"2026-12-31"},{"name":"sort","in":"query","required":false,"description":"Sort field. Allowed: start_date, end_date, created_at. Prefix with - for descending.","schema":{"type":"string"},"example":"-start_date"},{"name":"include","in":"query","required":false,"description":"Comma-separated related resources to include. Allowed: employee, requester.","schema":{"type":"string"},"example":"employee"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":2000,"default":15},"example":15}],"responses":{"200":{"description":"Paginated list of absence transactions for the employee.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record, or lacks permission to view the requested employee's absences.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/absence-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusAbsences"],"summary":"List pending absence requests for a PBX (user)","operationId":"tempusListAbsenceRequests","description":"Returns a paginated list of pending absence requests (debit transactions of type absence, legal holiday, illness or special) for the PBX. Callers without a validator scope only see their own requests unless they filter by group or employee. The response is a standard Laravel paginated collection.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[from]","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Lower bound for the absence period.","example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Upper bound for the absence period.","example":"2026-01-31"},{"name":"filter[status]","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of statuses to filter by.","example":"pending"},{"name":"filter[department_id]","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of Tempus department ids; matches employees whose active contract is in one of these departments.","example":"550e8400-e29b-41d4-a716-446655440010"},{"name":"filter[employee_id]","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of employee IDs to filter by.","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"sort","in":"query","required":false,"schema":{"type":"string"},"description":"Sort field (start, end, start_date, end_date, created_at, status). Prefix with - for descending.","example":"-created_at"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Page number.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":2000},"description":"Items per page (default 15).","example":15}],"responses":{"200":{"description":"Paginated list of absence requests.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record or lacks permission to view the requested absences."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/absence-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusAbsences"],"summary":"List absence requests for a specific employee (user)","operationId":"tempusListUserAbsenceRequests","description":"Returns a paginated list of absence requests (debit transactions of type absence, legal holiday, illness or special) for the given employee. Callers may only view their own requests unless they hold a validator scope over the employee. The response is a standard Laravel paginated collection.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the employee.","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Lower bound for the absence period.","example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Upper bound for the absence period.","example":"2026-01-31"},{"name":"filter[status]","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of statuses to filter by.","example":"pending"},{"name":"sort","in":"query","required":false,"schema":{"type":"string"},"description":"Sort field (start, end, start_date, end_date, created_at, status). Prefix with - for descending.","example":"-created_at"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Page number.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":2000},"description":"Items per page (default 15).","example":15}],"responses":{"200":{"description":"Paginated list of the employee's absence requests.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record or is not allowed to view this employee's absences."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusAbsences"],"summary":"Create an absence request for a specific employee (user)","operationId":"tempusCreateAbsenceRequest","description":"Creates a new pending absence request for the employee. Requested time is expressed in seconds for the first and last day; weekends, public holidays, special holidays and dates already covered by other absences are skipped. If no working day remains after skipping, a 422 is returned.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the employee.","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["start","end","requested_time_first_day","requested_time_last_day"],"properties":{"company_id":{"type":["string","null"],"format":"uuid","description":"Company the absence belongs to. Must exist for the PBX and the employee's contract.","example":"550e8400-e29b-41d4-a716-446655440020"},"start":{"type":"string","format":"date","description":"First day of the absence.","example":"2026-03-02"},"end":{"type":"string","format":"date","description":"Last day of the absence. Must be equal to or after start.","example":"2026-03-06"},"requested_time_first_day":{"type":"integer","minimum":1,"maximum":86400,"description":"Requested time on the first day, in seconds, expressed as a fraction of a nominal 8h day: send 28800 for a whole day and 14400 for a half day. The server scales that to the employee's own scheduled day, so a whole day for somebody contracted to 4h stores 14400 and a half of it stores 7200. Only the first and last day of a range can be a half day; on a single-day request this value is the one that applies. Days between the two ends take the employee's full scheduled seconds for that weekday.\n","example":28800},"requested_time_last_day":{"type":"integer","minimum":1,"maximum":86400,"description":"Requested time on the last day, in seconds, as a fraction of a nominal 8h day. Same scaling as `requested_time_first_day`. Ignored when start and end are the same date.\n","example":28800},"comment":{"type":["string","null"],"maxLength":65535,"description":"Optional note attached to the request.","example":"Family trip"},"type":{"type":["string","null"],"enum":["absence","legal","illness","special"],"description":"Absence type. Defaults to `legal` when omitted. `absence` is DEPRECATED \u2014 it was only ever a second name for `legal` and is stored as `legal`; responses always report `legal`.","example":"legal"},"sub_type":{"type":["string","null"],"maxLength":255,"description":"Optional sub type label.","example":"planned"}}}}}},"responses":{"201":{"description":"The created absence request.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusTransaction"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record or is not allowed to create absences for this employee."},"422":{"description":"Validation failed, or the requested period contains nothing bookable. The second case is returned when every date in the range is a weekend, a public holiday, a company special holiday, a day another absence already covers, or a day the employee's work shift schedules no hours for. It carries a bare `message` with no field-keyed `errors` object, so branch on whether `errors` is present.\n","content":{"application\/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"No working days available in the selected date range."},"errors":{"type":"object","description":"Present only for field validation failures, keyed by input field name. Absent when the period simply contains no bookable day.\n","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"examples":{"noWorkingDays":{"summary":"The period contains no bookable day","value":{"message":"No working days available in the selected date range."}},"validationFailed":{"summary":"Field validation failed","value":{"message":"The given data was invalid.","errors":{"end":["The end field must be a date after or equal to start."]}}}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/absence-requests\/{absence_request_id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"put":{"tags":["TempusAbsences"],"summary":"Update a pending absence request for an employee (user)","operationId":"tempusUpdateAbsenceRequest","description":"Updates a pending absence request. Only pending requests can be modified; any other status returns a 422. Dates and requested times default to the existing values when omitted. Sending a cancelling status only updates the status. The requested time is recalculated against weekends, public holidays, special holidays and overlapping absences.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the employee.","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"absence_request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the absence request transaction.","example":"550e8400-e29b-41d4-a716-446655440030"}],"requestBody":{"required":false,"content":{"application\/json":{"schema":{"type":"object","properties":{"company_id":{"type":["string","null"],"format":"uuid","description":"Company the absence belongs to. Must exist for the PBX and the employee's contract.","example":"550e8400-e29b-41d4-a716-446655440020"},"start":{"type":"string","format":"date","description":"First day of the absence.","example":"2026-03-02"},"end":{"type":"string","format":"date","description":"Last day of the absence. Must be equal to or after start.","example":"2026-03-06"},"requested_time_first_day":{"type":"integer","minimum":1,"maximum":86400,"description":"Requested time on the first day, in seconds, expressed as a fraction of a nominal 8h day: send 28800 for a whole day and 14400 for a half day. The server scales that to the employee's own scheduled day, so a whole day for somebody contracted to 4h stores 14400 and a half of it stores 7200. Days between the two ends take the employee's full scheduled seconds for that weekday. Omit to keep the value already stored on the request.\n","example":28800},"requested_time_last_day":{"type":"integer","minimum":1,"maximum":86400,"description":"Requested time on the last day, in seconds, as a fraction of a nominal 8h day. Same scaling as `requested_time_first_day`. Ignored when start and end are the same date. Omit to keep the value already stored on the request.\n","example":28800},"comment":{"type":["string","null"],"maxLength":65535,"description":"Optional note attached to the request.","example":"Updated note"},"type":{"type":"string","enum":["absence","legal","illness","special"],"description":"Absence type. `absence` is DEPRECATED \u2014 it was only ever a second name for `legal` and is stored as `legal`; responses always report `legal`.","example":"legal"},"sub_type":{"type":["string","null"],"maxLength":255,"description":"Optional sub type label.","example":"planned"},"status":{"type":"string","enum":["cancelled","canceled"],"description":"Set to a cancelling status to cancel the request without changing other fields.","example":"cancelled"}}}}}},"responses":{"200":{"description":"The updated absence request.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusTransaction"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record or is not allowed to update this request."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/absence-requests\/{absence_request_id}\/cancel":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusAbsences"],"summary":"Cancel an absence request, or take back its cancellation (user)","operationId":"tempusCancelAbsenceRequest","description":"The single endpoint an employee uses to undo an absence, at whatever stage it\nhas reached. What it does depends on the current status of the request:\n\n| Current status | What happens | Response `status` |\n|---|---|---|\n| `pending` | Cancelled outright. Pending approvals are deleted and no validator is asked. | `canceled` |\n| `accepted` (internally `approved`) | Cannot be deleted directly. A **removal request** (a credit transaction, `sub_type: removal`) is created and the original moves to `pending_removal`; a validator must approve the removal before the days come back. | `pending` (of the new removal row) |\n| `pending_removal` | The open removal is **revoked**: it is cancelled and the absence returns to `accepted`. The days stay booked, exactly as if a validator had rejected the removal. | `accepted` |\n| anything else (`rejected`, `removed`, `canceled`) | Nothing. `400`. | n\/a |\n\n### Taking back a cancellation\n\nThe `pending_removal` row is what makes this endpoint reversible. An employee\nwho asked for an approved holiday to be given back - either through this\nendpoint or through `POST \/{pbx_id}\/user\/{employee_id}\/absence-removal-requests` -\ncan change their mind for as long as no validator has ruled, and keep the days.\n\nYou may address that revocation with **either id**:\n\n- the **original absence** id (status `pending_removal`) - the row the employee\n  sees in their calendar, and the id a client normally holds; or\n- the **removal request** id (status `pending`, `sub_type: removal`) - the\n  credit row created when the removal was opened.\n\nBoth land on the same state and both answer with the **restored original\nabsence**, never with the withdrawn credit row. Revoking also deletes the\nremoval's pending approvals, so no validator is left holding a decision that no\nlonger matters.\n\nRevocation is not one-way: once the absence is back to `accepted`, calling this\nendpoint again simply opens a fresh removal request.\n\n### Emails\n\nA withdrawal the employee performs themselves is confirmed by email to the\nemployee the absence belongs to, and to whoever filed it when that is someone\nelse. Two different messages are sent:\n\n- **request cancelled** - a `pending` request was withdrawn;\n- **cancellation withdrawn** - a `pending_removal` was revoked and the days\n  stay booked.\n\nOpening a removal (the `accepted` branch) sends no such confirmation: nothing\nhas been withdrawn yet, and the validators are notified instead.\n\n### Authorization\n\nOwner-based: only the employee the request belongs to may cancel it, regardless\nof who created it on their behalf. The request is resolved by its own id, so\nthe `{employee_id}` path segment is **not** used for authorization - a request\nthat genuinely does not exist returns `404`, one that exists but is not the\ncaller's returns `403`.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the employee (path segment only; not used for authorization - the request is resolved by its own id and cancel is owner-based).\n","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"absence_request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the absence request transaction. To revoke a cancellation this may be either the original absence (status `pending_removal`) or its pending removal request (`sub_type: removal`) - both are accepted.\n","example":"550e8400-e29b-41d4-a716-446655440030"}],"requestBody":{"required":false,"description":"No body. The outcome is decided entirely by the current status of the addressed request; send an empty body or omit it.\n"},"responses":{"200":{"description":"The affected absence request, serialized by the V1 transaction resource\n(unwrapped - the object is the response body, there is no `data` envelope).\n\nWhich row you get back depends on the branch taken: the cancelled request,\nthe newly created pending removal, or the restored original absence. Switch\non `status` and `sub_type` rather than assuming.\n","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusTransaction"},"examples":{"pendingCancelled":{"summary":"A pending request was withdrawn","description":"Nothing was booked yet, so the request is simply cancelled and its pending approvals are dropped.\n","value":{"id":"550e8400-e29b-41d4-a716-446655440030","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","employee_id":"550e8400-e29b-41d4-a716-446655440001","requester_id":"550e8400-e29b-41d4-a716-446655440001","creator_id":"550e8400-e29b-41d4-a716-446655440001","ext_id":"EXT-10293","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440030","holiday_id":null,"status":"canceled","type":"legal","sub_type":null,"start":"2026-09-14T00:00:00+00:00","end":"2026-09-15T00:00:00+00:00","requested_time":{"2026-09-14":28800,"2026-09-15":28800},"working_days":2,"total_seconds":57600,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-09-14","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-09-15","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":"Changed my plans.","accepted_by":[],"created":"2026-09-01T10:00:00+00:00","modified":"2026-09-02T08:15:00+00:00"}},"removalOpened":{"summary":"An approved absence opened a removal request","description":"The response is the NEW credit row (`sub_type: removal`), not the original. The original is now `pending_removal` and the days stay booked until a validator approves this removal.\n","value":{"id":"550e8400-e29b-41d4-a716-446655440077","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","employee_id":"550e8400-e29b-41d4-a716-446655440001","requester_id":"550e8400-e29b-41d4-a716-446655440001","creator_id":"550e8400-e29b-41d4-a716-446655440001","ext_id":"EXT-10293","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440077","holiday_id":null,"status":"pending","type":"legal","sub_type":"removal","start":"2026-08-03T00:00:00+00:00","end":"2026-08-05T00:00:00+00:00","requested_time":{"2026-08-03":28800,"2026-08-04":28800,"2026-08-05":28800},"working_days":3,"total_seconds":86400,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-03","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-04","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-05","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":"Family event, returning Thursday.","accepted_by":[{"employee_id":"550e8400-e29b-41d4-a716-446655440004","status":"pending"}],"created":"2026-08-06T09:00:00+00:00","modified":"2026-08-06T09:00:00+00:00"}},"removalRevoked":{"summary":"A pending removal was revoked - the days stay booked","description":"Returned whether you addressed the original absence or its removal row. The removal is now `canceled` and this absence is `accepted` again.\n","value":{"id":"550e8400-e29b-41d4-a716-446655440030","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","employee_id":"550e8400-e29b-41d4-a716-446655440001","requester_id":"550e8400-e29b-41d4-a716-446655440001","creator_id":"550e8400-e29b-41d4-a716-446655440001","ext_id":"EXT-10293","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440030","holiday_id":null,"status":"accepted","type":"legal","sub_type":null,"start":"2026-08-03T00:00:00+00:00","end":"2026-08-05T00:00:00+00:00","requested_time":{"2026-08-03":28800,"2026-08-04":28800,"2026-08-05":28800},"working_days":3,"total_seconds":86400,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-03","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-04","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-05","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":"Family event, returning Thursday.","accepted_by":[{"employee_id":"550e8400-e29b-41d4-a716-446655440004","status":"accepted"}],"created":"2026-07-28T10:00:00+00:00","modified":"2026-08-06T11:42:00+00:00"}}}}}},"400":{"description":"The request is in a status that cannot be cancelled - `rejected`, `removed` or already `canceled`. Only `pending`, `accepted` and `pending_removal` rows can be acted on.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Only pending, approved or pending-removal absence requests can be cancelled."}}},"example":{"message":"Only pending, approved or pending-removal absence requests can be cancelled."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The request exists but does not belong to the authenticated user (only its owner may cancel it)."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/absence-removal-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusAbsences"],"summary":"Request removal of an approved legal holiday absence (user)","operationId":"tempusCreateAbsenceRemovalRequest","description":"Creates a pending removal request to credit back an approved legal holiday\nabsence. The referenced absence must be an approved legal holiday debit\ntransaction with no pending removal already in flight. The original absence\nmoves to a pending-removal status and the created credit transaction must be\nvalidated.\n\n**This is reversible.** For as long as no validator has ruled, the employee can\ntake the removal back and keep the days, via\n`POST \/{pbx_id}\/user\/{employee_id}\/absence-requests\/{absence_request_id}\/cancel`.\nThat endpoint accepts either the original absence's id (now `pending_removal`)\nor the `id` returned here, and restores the absence to `accepted`.\n\nThe same cancel endpoint is also the shorter way to *open* a removal: calling\nit on an approved absence creates exactly the row this endpoint does. Use this\nendpoint when you want to attach a `comment` to the removal.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the employee.","example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["absence_id"],"properties":{"absence_id":{"type":"string","format":"uuid","description":"UUID of the approved legal holiday absence to remove.","example":"550e8400-e29b-41d4-a716-446655440030"},"comment":{"type":["string","null"],"maxLength":65535,"description":"Optional note attached to the removal request.","example":"Cancelling planned leave"}}}}}},"responses":{"201":{"description":"The created pending removal request.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusTransaction"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record or is not allowed to create removal requests for this employee."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/absence-requests\/{absence_request_id}\/validations":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusAbsences"],"summary":"List validations for an absence request (user)","operationId":"tempusListAbsenceRequestValidations","description":"Returns the paginated list of validation (approval) records for a single\nabsence request. Each record is one validator's decision on the request:\npending, accepted, or rejected, with an optional comment. The authenticated\nuser must be allowed to view approvals for the request.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"absence_request_id","in":"path","required":true,"description":"UUID of the absence request (Tempus transaction).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of records per page (maximum 100, defaults to 15).","schema":{"type":"integer","minimum":1,"maximum":100},"example":15}],"responses":{"200":{"description":"Paginated list of absence request validations.","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransactionApproval"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not allowed to view approvals for this absence request.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusAbsences"],"summary":"Submit a validation decision for an absence request (user)","operationId":"tempusCreateAbsenceRequestValidation","description":"Records the authenticated validator's decision (accepted or rejected) on an\nabsence request. The user must have an employee record and be allowed to\ncreate an approval for the request. If the validator already submitted a\nfinal decision, the request is rejected with a conflict.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"absence_request_id","in":"path","required":true,"description":"UUID of the absence request (Tempus transaction).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["accepted","rejected"],"description":"The validation decision for the absence request.","example":"accepted"},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional free-form note explaining the decision.","example":"Approved, please coordinate handover with the team."}}},"example":{"status":"accepted","comment":"Approved, please coordinate handover with the team."}}}},"responses":{"201":{"description":"The validation decision was recorded.","content":{"application\/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"Absence request validation created."}}}}}},"400":{"description":"The absence request is no longer in a pending state and cannot be validated.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The absence request is not pending."}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no employee record or is not allowed to create\nan approval for this absence request.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"An employee record is required to perform this action."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"A final validation decision has already been submitted by this validator.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This absence request has already been validated."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/home-office-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusHomeOffice"],"summary":"List home office requests (tenant-wide, validator-scoped)","operationId":"tempusListHomeOfficeRequests","description":"Return a paginated list of home office requests (Tempus transactions of type\n`home_office`) across the PBX. The acting user must have a linked Tempus\nemployee record. When the user is not a validator with home office scope and\nno `filter[department_id]` or `filter[employee_id]` is supplied, results are\nlimited to the acting user's own requests. Validators may filter by\n`employee_id` or `department_id` within their scope.\n\nFor a single employee's requests use\n`GET \/{pbx_id}\/user\/{employee_id}\/home-office-requests` instead.\n\nEach item is serialized by the V1 transaction resource. The list is wrapped in\nthe standard Laravel pagination envelope (`data`, `links`, `meta`).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the PBX tenant","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"filter[from]","in":"query","required":false,"description":"Start of the date window the request period must overlap.","schema":{"type":"string","format":"date","example":"2024-03-01"}},{"name":"filter[to]","in":"query","required":false,"description":"End of the date window the request period must overlap.","schema":{"type":"string","format":"date","example":"2024-03-31"}},{"name":"filter[status]","in":"query","required":false,"description":"Comma-separated list of statuses to filter by. Accepts API aliases:\n`accepted` maps to the internal `approved`, `canceled` maps to the\ninternal `cancelled`.\n","schema":{"type":"string","example":"accepted,pending"}},{"name":"filter[department_id]","in":"query","required":false,"description":"Comma-separated list of Tempus department ids; matches employees whose active contract is in one of these departments.","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440010"}},{"name":"filter[employee_id]","in":"query","required":false,"description":"Comma-separated list of employee identifiers to filter by.","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"sort","in":"query","required":false,"description":"Sort field. Supports `start`, `end`, `start_date`, `end_date`,\n`created_at`, `status`. Prefix with `-` for descending order.\n","schema":{"type":"string","example":"-start_date"}},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1,"example":1}},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"example":15}}],"responses":{"200":{"description":"Paginated list of home office requests","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The acting user has no linked Tempus employee record, or the policy\n`viewAny` check denied access.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/home-office-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusHomeOffice"],"summary":"List a specific employee's home office requests","operationId":"tempusListUserHomeOfficeRequests","description":"Return a paginated list of home office requests (Tempus transactions of type\n`home_office`) for the employee identified by the `employee_id` path\nparameter. The caller may view their own requests, or - when they are a\nvalidator - another employee's; otherwise `403` is returned. Results are\nalways scoped to the path employee (there is no `ext_id` filter here; use\n`GET \/{pbx_id}\/home-office-requests` for the tenant-wide, filterable list).\n\nEach item is serialized by the V1 transaction resource. The list is wrapped in\nthe standard Laravel pagination envelope (`data`, `links`, `meta`).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the PBX tenant","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the employee whose home office requests are listed","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"filter[from]","in":"query","required":false,"description":"Start of the date window the request period must overlap.","schema":{"type":"string","format":"date","example":"2024-03-01"}},{"name":"filter[to]","in":"query","required":false,"description":"End of the date window the request period must overlap.","schema":{"type":"string","format":"date","example":"2024-03-31"}},{"name":"filter[status]","in":"query","required":false,"description":"Comma-separated list of statuses to filter by. Accepts API aliases:\n`accepted` maps to the internal `approved`, `canceled` maps to the\ninternal `cancelled`.\n","schema":{"type":"string","example":"accepted,pending"}},{"name":"sort","in":"query","required":false,"description":"Sort field. Supports `start`, `end`, `start_date`, `end_date`,\n`created_at`, `status`. Prefix with `-` for descending order.\n","schema":{"type":"string","example":"-start_date"}},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1,"example":1}},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"example":15}}],"responses":{"200":{"description":"Paginated list of home office requests","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The acting user has no linked Tempus employee record, or is neither the\ntarget employee nor a validator, so may not view this employee's requests.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusHomeOffice"],"summary":"Request home office days for an employee (user)","operationId":"tempusCreateHomeOfficeRequest","description":"Request one or more home office days for the given employee. Each date in\n`dates` becomes its own pending Tempus transaction of type `home_office` (a\nper-day ledger row); all rows created by one call share a `request_group_id`.\nEach day debits a full working day (28800 seconds). Approval records are\ngenerated automatically.\n\nTenant (`pbx_id`), owning employee, requester, type, status and amounts are\nset server-side and must not be sent in the body. Dates that are public\nholidays, already booked as home office, or overlapping an absence are\nrejected with `422` and an `invalid_dates` payload.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the PBX tenant","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the employee the request is created for","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["dates"],"properties":{"dates":{"type":"array","minItems":1,"maxItems":100,"description":"Home office days to request, each `YYYY-MM-DD`. Every date must be\ntoday or later and within six months, and be unique. Each date\nbecomes its own pending transaction.\n","items":{"type":"string","format":"date","example":"2024-03-04"}},"comment":{"type":["string","null"],"maxLength":500,"description":"Optional free-form note attached to every created day-row.","example":"Working from home."}}},"example":{"dates":["2024-03-04","2024-03-06"],"comment":"Working from home."}}}},"responses":{"201":{"description":"The created home office day-rows, one per requested date. Wrapped in a `data` array.","content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The acting user has no linked Tempus employee record, or the policy\n`create` check denied access.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/home-office-requests\/cancel":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusHomeOffice"],"summary":"Withdraw home office days, or take back their cancellation (user)","operationId":"tempusCancelHomeOfficeRequests","description":"Withdraw one or more home office day-rows (Tempus transactions of type\n`home_office`) by id. Home office is stored one row per day, so this endpoint\nis a bulk operation: it is best-effort and decides per row from that row's\ncurrent status.\n\n| Current status | What happens | Reported under |\n|---|---|---|\n| `pending` | Cancelled directly; its pending approvals are deleted. | `cancelled` |\n| `accepted` (internally `approved`) | A **removal request** (credit row, `sub_type: removal`) is created and the day moves to `pending_removal`; a validator must approve it. | `cancelled` (the new removal row) |\n| `pending_removal` | The open removal is **revoked** and the day returns to `accepted` - the employee taking back their own cancellation. | `cancelled` (the restored day) |\n| `removed`, `canceled`, `rejected`, or an id that is not one of this employee's home office days | Nothing. | `skipped` |\n\nThe call always returns `200`: valid days are acted on even when others are\nskipped, and every id you sent is accounted for in exactly one of the two\nlists.\n\n### Taking back a cancellation\n\nA day whose removal is still waiting for validation can be given back to the\nemployee for as long as no validator has ruled. Pass **either id**:\n\n- the **original day** (status `pending_removal`), or\n- its **removal row** (status `pending`, `sub_type: removal`).\n\nBoth revoke the removal and both report the **restored original day** in\n`cancelled` - so an entry in `cancelled` is not always the row whose id you\nsent. Match on the returned objects, not positionally against your input.\n\nSending both ids of the same pair in one call is safe: the pair is revoked\nonce, the original appears in `cancelled`, and the removal row - already\ncancelled by then - is reported in `skipped` as `already_cancelled`.\n\n### Emails\n\nWithdrawing a `pending` day, and revoking a `pending_removal`, each confirm by\nemail to the employee (and to whoever filed the day, when that is someone\nelse). Opening a removal on an `accepted` day sends no confirmation - nothing\nhas been withdrawn yet, and the validators are notified instead.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the PBX tenant","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the employee who owns the requests","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"description":"Identifiers of the home office day-rows to act on. Each must be an\nexisting `home_office` transaction in this PBX belonging to this\nemployee. To revoke a cancellation, pass either the original day or\nits pending removal row.\n","items":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"}}}},"examples":{"withdrawPendingDays":{"summary":"Withdraw two days that are still waiting for validation","value":{"ids":["550e8400-e29b-41d4-a716-446655440030","550e8400-e29b-41d4-a716-446655440031"]}},"revokeByOriginalId":{"summary":"Take back the cancellation of a day whose removal is still pending","value":{"ids":["550e8400-e29b-41d4-a716-446655440040"]}},"mixedBatch":{"summary":"A mixed batch - one withdrawn, one revoked, one already removed","value":{"ids":["550e8400-e29b-41d4-a716-446655440030","550e8400-e29b-41d4-a716-446655440040","550e8400-e29b-41d4-a716-446655440050"]}}}}}},"responses":{"200":{"description":"The outcome of the call. `cancelled` holds the affected day-rows in their\nnew state - cancelled outright, moved to `pending_removal`, or restored to\n`accepted` after a revocation. `skipped` lists the ids that were not acted\non, each with a machine `reason` and a human `message`.\n","content":{"application\/json":{"schema":{"type":"object","required":["cancelled","skipped"],"properties":{"cancelled":{"type":"array","description":"The resulting day-rows, in their new state. Not necessarily the rows whose ids you sent: revoking by a removal row's id reports the restored original instead.\n","items":{"$ref":"#\/components\/schemas\/TempusTransaction"}},"skipped":{"type":"array","description":"Requested ids that were not acted on, each with the reason why.","items":{"type":"object","required":["id","status","reason","message"],"properties":{"id":{"type":"string","format":"uuid","description":"The requested day-row id.","example":"550e8400-e29b-41d4-a716-446655440050"},"status":{"type":["string","null"],"description":"Current internal status of the row, or null when the id did not resolve to one of this employee's home office days.\n","enum":["removed","cancelled","rejected",null],"example":"removed"},"reason":{"type":"string","description":"Machine-readable skip reason.","enum":["already_removed","already_cancelled","not_cancellable","not_found"],"example":"already_removed"},"message":{"type":"string","description":"Human-readable explanation, suitable for display.","example":"This date has already been removed."}}}}}},"examples":{"pendingWithdrawn":{"summary":"A pending day was withdrawn","value":{"cancelled":[{"id":"550e8400-e29b-41d4-a716-446655440030","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","employee_id":"550e8400-e29b-41d4-a716-446655440001","requester_id":"550e8400-e29b-41d4-a716-446655440001","creator_id":"550e8400-e29b-41d4-a716-446655440001","ext_id":"EXT-10293","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440030","holiday_id":null,"status":"canceled","type":"home_office","sub_type":null,"start":"2026-09-14T00:00:00+00:00","end":"2026-09-14T00:00:00+00:00","requested_time":{"2026-09-14":28800},"working_days":1,"total_seconds":28800,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-09-14","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":null,"accepted_by":[],"created":"2026-09-01T10:00:00+00:00","modified":"2026-09-02T08:15:00+00:00"}],"skipped":[]}},"removalRevoked":{"summary":"A pending removal was revoked - the day stays booked","description":"Returned whether you addressed the original day or its removal row. `status` is back to `accepted`.\n","value":{"cancelled":[{"id":"550e8400-e29b-41d4-a716-446655440040","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","employee_id":"550e8400-e29b-41d4-a716-446655440001","requester_id":"550e8400-e29b-41d4-a716-446655440001","creator_id":"550e8400-e29b-41d4-a716-446655440001","ext_id":"EXT-10293","company_id":"550e8400-e29b-41d4-a716-446655440003","absence_request_id":"550e8400-e29b-41d4-a716-446655440040","holiday_id":null,"status":"accepted","type":"home_office","sub_type":null,"start":"2026-08-10T00:00:00+00:00","end":"2026-08-10T00:00:00+00:00","requested_time":{"2026-08-10":28800},"working_days":1,"total_seconds":28800,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-10","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}],"comment":null,"accepted_by":[{"employee_id":"550e8400-e29b-41d4-a716-446655440004","status":"accepted"}],"created":"2026-07-30T10:00:00+00:00","modified":"2026-08-06T11:42:00+00:00"}],"skipped":[]}},"mixedOutcome":{"summary":"One withdrawn, one revoked, one skipped","description":"The three ids from the `mixedBatch` request body. Note the shapes differ per row - switch on `status` and `sub_type`.\n","value":{"cancelled":[{"id":"550e8400-e29b-41d4-a716-446655440030","status":"canceled","type":"home_office","sub_type":null,"employee_id":"550e8400-e29b-41d4-a716-446655440001","start":"2026-09-14T00:00:00+00:00","end":"2026-09-14T00:00:00+00:00","working_days":1,"total_seconds":28800},{"id":"550e8400-e29b-41d4-a716-446655440040","status":"accepted","type":"home_office","sub_type":null,"employee_id":"550e8400-e29b-41d4-a716-446655440001","start":"2026-08-10T00:00:00+00:00","end":"2026-08-10T00:00:00+00:00","working_days":1,"total_seconds":28800}],"skipped":[{"id":"550e8400-e29b-41d4-a716-446655440050","status":"removed","reason":"already_removed","message":"This date has already been removed."}]}},"allSkipped":{"summary":"Nothing could be acted on","value":{"cancelled":[],"skipped":[{"id":"550e8400-e29b-41d4-a716-446655440060","status":null,"reason":"not_found","message":"This home office day could not be found for this employee."},{"id":"550e8400-e29b-41d4-a716-446655440061","status":"rejected","reason":"not_cancellable","message":"This date cannot be cancelled."}]}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The policy `create` check denied access for this employee."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/home-office-requests\/{home_office_request_id}\/validations":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusHomeOffice"],"summary":"List validations for a home office request (user)","operationId":"tempusListHomeOfficeRequestValidations","description":"Returns the paginated list of validation (approval) records for a single\nhome office request. The home office request is resolved from the underlying\nTempus transaction, scoped to the authenticated tenant. Each record\nrepresents one validator's decision on the request.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"home_office_request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the home office request (Tempus transaction)","example":"550e8400-e29b-41d4-a716-446655440030"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Page number to retrieve.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"Number of records per page (defaults to 15).","example":15}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTransactionApproval"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440040","mxvp_user_id":"550e8400-e29b-41d4-a716-446655440000","absence_request_id":"550e8400-e29b-41d4-a716-446655440030","ext_id":"201","validator":{"id":"550e8400-e29b-41d4-a716-446655440003","name":"Jane Smith"},"status":"accepted","comment":"Approved as requested.","create_time":"2024-03-01T08:29:07+00:00","modified":"2024-03-01T09:15:42+00:00","holiday_id":null}],"links":{"first":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/resources?page=1","last":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/resources?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"path":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/resources","per_page":15,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden: the authenticated user is not allowed to view validations for this home office request.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"This action is unauthorized."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusHomeOffice"],"summary":"Submit a validation decision for a home office request (user)","operationId":"tempusCreateHomeOfficeRequestValidation","description":"Records the authenticated validator's decision (accepted or rejected) on a\nhome office request and processes the approval against the underlying Tempus\ntransaction. The authenticated user must have an associated employee record.\nA validator may only submit one decision per request.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"home_office_request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the home office request (Tempus transaction)","example":"550e8400-e29b-41d4-a716-446655440030"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["accepted","rejected"],"description":"The validation decision for the home office request.","example":"accepted"},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional free-form note explaining the decision.","example":"Approved as requested."}}},"example":{"status":"accepted","comment":"Approved as requested."}}}},"responses":{"201":{"description":"Created","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"Validation created successfully."}}}},"400":{"description":"Bad Request: the home office request is not in pending status and cannot be validated.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"The request is not pending and cannot be validated."}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden: the authenticated user is not allowed to validate this request, or has no associated employee record.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"This action is unauthorized."}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"Conflict: the authenticated validator has already submitted a decision for this request.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}},"example":{"message":"You have already validated this request."}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/home-office-requests\/validations":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusHomeOffice"],"summary":"Validate several home office day-rows at once","operationId":"tempusBulkValidateHomeOfficeRequests","description":"Apply a single decision (`accepted` or `rejected`) to several home office\nday-rows in one call, for example a whole request group or week. The acting\nuser must be a validator with home office scope over the affected employees.\n\nRows that are not `pending`, or that the acting validator has already decided,\nare skipped rather than failing the batch. The response reports how many rows\nwere processed and skipped.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the PBX tenant","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["ids","status"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"description":"Identifiers of the home office day-rows to validate.","items":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"}},"status":{"type":"string","enum":["accepted","rejected"],"description":"The decision to apply to every listed row.","example":"accepted"},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional note stored on each created approval.","example":"Approved for the whole week."}}},"example":{"ids":["550e8400-e29b-41d4-a716-446655440030","550e8400-e29b-41d4-a716-446655440031"],"status":"accepted"}}}},"responses":{"200":{"description":"The decision was applied. Reports processed and skipped counts.","content":{"application\/json":{"schema":{"type":"object","required":["message","processed","skipped"],"properties":{"message":{"type":"string","example":"Validation completed."},"processed":{"type":"integer","description":"Number of rows a decision was recorded for.","example":2},"skipped":{"type":"integer","description":"Rows skipped (not pending, or already decided by this validator).","example":0}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The acting user is not a validator for one of the listed rows."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/home-office-calendars":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusHomeOffice"],"summary":"List home office calendars across employees (user)","operationId":"tempusListHomeOfficeCalendars","description":"Returns virtual home office calendar entries aggregated from `home_office`\ntransactions across the tenant. Each entry groups the pending, approved, and\nremoved home-office days for one employee, company, and calendar year.\n\nWhen the caller has permission to view other employees' home office\n(resolved from the validator scope), entries for the caller's company are\nreturned; without a group filter the result is scoped to the caller's\ncompany. Otherwise only the caller's own entries are returned. The response\nis a plain list under `data` and is not paginated, even though `page` and\n`per_page` are accepted as filters.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[year]","in":"query","required":false,"schema":{"type":"integer","minimum":2000,"maximum":2100},"description":"Restrict the calendars to a single calendar year.","example":2026},{"name":"filter[group_id]","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Restrict the calendars to employees in a specific department group.","example":"550e8400-e29b-41d4-a716-446655440010"},{"name":"include","in":"query","required":false,"schema":{"type":"string","enum":["user"]},"description":"When set to `user`, embeds the linked Voxbi user summary on each entry.","example":"user"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Accepted for compatibility; the response is not paginated.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"Accepted for compatibility; the response is not paginated.","example":15}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusHomeOfficeCalendar"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user does not belong to the requested PBX\ntenant.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/home-office-calendars":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusHomeOffice"],"summary":"List home office calendars for one employee (user)","operationId":"tempusListUserHomeOfficeCalendars","description":"Returns the virtual home office calendar entries for a single employee,\naggregated from that employee's `home_office` transactions and grouped by\ncompany and calendar year. The response is a plain list under `data` and is\nnot paginated, even though `page` and `per_page` are accepted as filters.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose calendars are returned.","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[year]","in":"query","required":false,"schema":{"type":"integer","minimum":2000,"maximum":2100},"description":"Restrict the calendars to a single calendar year.","example":2026},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Accepted for compatibility; the response is not paginated.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"Accepted for compatibility; the response is not paginated.","example":15}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusHomeOfficeCalendar"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/calendar\/absence":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCalendar"],"summary":"Company absence calendar","operationId":"tempusAbsenceCalendar","description":"Lightweight absence calendar for the caller's company: every colleague's absence, illness, special and legal-holiday bookings in the `pending`, `approved` and `pending_removal` states. Any employee in the company may read it (a team availability view); this is intentionally not scoped to the caller's own records and carries only the fields a calendar needs - full request detail lives on the `absence-requests` endpoints. The response is a flat array, not wrapped in a `data` envelope and not paginated. Cancellation-in-progress rows appear once (the original, as `pending_removal`); the internal removal credit is omitted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[department_id]","in":"query","required":false,"description":"Narrow to one or more departments (comma-separated), by the employee's active contract. Omit for the whole company.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440042"},{"name":"filter[from]","in":"query","required":false,"description":"Only events overlapping on or after this date (`Y-m-d`).","schema":{"type":"string","format":"date"},"example":"2026-07-01"},{"name":"filter[to]","in":"query","required":false,"description":"Only events overlapping on or before this date (`Y-m-d`).","schema":{"type":"string","format":"date"},"example":"2026-07-31"}],"responses":{"200":{"description":"The company absence calendar. Flat array, not wrapped in data, not paginated.","content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"employee_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_name":{"type":["string","null"],"example":"Jane Smith"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the employee's active contract; null when none.","example":"550e8400-e29b-41d4-a716-446655440042"},"type":{"type":"string","enum":["absence","illness","special","legal"],"example":"absence"},"sub_type":{"type":["string","null"],"description":"Absence sub-type where applicable (e.g. special_holiday).","example":null},"status":{"type":"string","enum":["pending","approved","pending_removal"],"example":"approved"},"start":{"type":"string","format":"date","example":"2026-07-07"},"end":{"type":"string","format":"date","example":"2026-07-09"},"total_seconds":{"type":"integer","description":"Total booked time across all days, in seconds.","example":86400},"days":{"type":"array","description":"Every entry of the booking's raw per-day map, in stored order. Rows written before that map held working days only carry a `0` for each weekend and public holiday inside the range, so this array can be longer than the days actually taken. `working_day_details` below is the same breakdown with those dropped and the half-day hours resolved; both are returned, and this one is unchanged.\n","items":{"type":"object","properties":{"date":{"type":"string","format":"date","example":"2026-07-07"},"seconds":{"type":"integer","example":28800}}}},"working_days":{"type":"number","description":"How long the booking is, in working days the employee actually consumes: weekends, public holidays, company special holidays and days already taken by another absence are excluded, and each remaining day is measured against that employee's own scheduled day. A part-timer's 4h day therefore counts as 1, while 4h out of an 8h day counts as 0.5. Whole counts serialize without a fractional part (3, not 3.0), so decode this as a float rather than an integer.\n","example":3},"workshift_seconds_per_day":{"type":"integer","description":"What one full working day is worth for this employee, in seconds: 28800 on a standard 8h shift, 14400 for somebody contracted to 4h days. Use it instead of assuming 8h. 0 when no contract or work shift resolves, which should be read as unknown.\n","example":28800},"is_half_day":{"type":"boolean","description":"True when either end of the booking is a half day.","example":false},"starts_half_day":{"type":"boolean","description":"True when the first day is a half day: the employee works that morning and then leaves. `start_time` carries the hour.\n","example":false},"ends_half_day":{"type":"boolean","description":"True when the last day is a half day: the absence covers that morning and the employee is back afterwards. `end_time` carries the hour. On a single-day half day this and `starts_half_day` are both true.\n","example":false},"start_time":{"type":["string","null"],"description":"Local wall-clock hour (HH:MM) the absence begins on a half-day start, null otherwise. Taken from the booking's own stored time when it has one, else the tenant's configured AM\/PM split (default 12:00).\n","example":null},"end_time":{"type":["string","null"],"description":"Local wall-clock hour (HH:MM) the absence ends on a half-day end, null otherwise. Same source as `start_time`.\n","example":null},"working_day_details":{"type":"array","description":"Per-day breakdown holding working days only, ascending by date, with the half-day verdict and hours resolved per day. Hours only ever land on the two ends: a day in the middle of a range has no clock time of its own, and a single-day booking is both ends at once.\n","items":{"type":"object","properties":{"date":{"type":"string","format":"date","example":"2026-07-07"},"seconds":{"type":"integer","description":"Seconds booked off that day, scaled to the employee's own day.","example":28800},"is_half_day":{"type":"boolean","description":"True when this day's seconds fall short of `workshift_seconds_per_day` by more than 900 (a tolerance for lunch and rounding).\n","example":false},"start_time":{"type":["string","null"],"description":"HH:MM; non-null only on a half-day first day.","example":null},"end_time":{"type":["string","null"],"description":"HH:MM; non-null only on a half-day last day.","example":null}}}}}}},"examples":{"spanningAWeekend":{"summary":"A booking written before the per-day map held working days only","description":"Fri 2026-08-07 to Mon 2026-08-10, a half day on the Friday. `days` still carries the weekend as two 0-second entries, which is why it has four items where `working_day_details` has two.\n","value":[{"id":"550e8400-e29b-41d4-a716-446655440030","employee_id":"550e8400-e29b-41d4-a716-446655440001","employee_name":"Jane Smith","department_id":"550e8400-e29b-41d4-a716-446655440042","type":"legal","sub_type":null,"status":"approved","start":"2026-08-07","end":"2026-08-10","total_seconds":43200,"days":[{"date":"2026-08-07","seconds":14400},{"date":"2026-08-08","seconds":0},{"date":"2026-08-09","seconds":0},{"date":"2026-08-10","seconds":28800}],"working_days":1.5,"workshift_seconds_per_day":28800,"is_half_day":true,"starts_half_day":true,"ends_half_day":false,"start_time":"12:00","end_time":null,"working_day_details":[{"date":"2026-08-07","seconds":14400,"is_half_day":true,"start_time":"12:00","end_time":null},{"date":"2026-08-10","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}]}]},"wholeWeek":{"summary":"A whole Monday to Friday, no half day","value":[{"id":"550e8400-e29b-41d4-a716-446655440031","employee_id":"550e8400-e29b-41d4-a716-446655440002","employee_name":"Alex Doe","department_id":null,"type":"illness","sub_type":null,"status":"pending","start":"2026-08-03","end":"2026-08-07","total_seconds":144000,"days":[{"date":"2026-08-03","seconds":28800},{"date":"2026-08-04","seconds":28800},{"date":"2026-08-05","seconds":28800},{"date":"2026-08-06","seconds":28800},{"date":"2026-08-07","seconds":28800}],"working_days":5,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-03","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-07","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}]}]},"partTimer":{"summary":"A part-timer on 4h days, two whole days off","description":"`workshift_seconds_per_day` is 14400, so 14400 per day is a WHOLE day and `is_half_day` is false. Reading 8h would have called these half days.\n","value":[{"id":"550e8400-e29b-41d4-a716-446655440032","employee_id":"550e8400-e29b-41d4-a716-446655440005","employee_name":"Sam Lee","department_id":null,"type":"legal","sub_type":null,"status":"approved","start":"2026-08-03","end":"2026-08-04","total_seconds":28800,"days":[{"date":"2026-08-03","seconds":14400},{"date":"2026-08-04","seconds":14400}],"working_days":2,"workshift_seconds_per_day":14400,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-03","seconds":14400,"is_half_day":false,"start_time":null,"end_time":null},{"date":"2026-08-04","seconds":14400,"is_half_day":false,"start_time":null,"end_time":null}]}]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller belongs to another tenant, has no employee record, or has no active company."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/calendar\/home-office":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCalendar"],"summary":"Company home office calendar","operationId":"tempusHomeOfficeCalendar","description":"Lightweight home office calendar for the caller's company: every colleague's home office bookings in the `pending`, `approved` and `pending_removal` states. Any employee in the company may read it (a team availability view); this is intentionally not scoped to the caller's own records and carries only the fields a calendar needs - full request detail lives on the `home-office-requests` endpoints. The response is a flat array, not wrapped in a `data` envelope and not paginated. Cancellation-in-progress rows appear once (the original, as `pending_removal`); the internal removal credit is omitted.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[department_id]","in":"query","required":false,"description":"Narrow to one or more departments (comma-separated), by the employee's active contract. Omit for the whole company.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440042"},{"name":"filter[from]","in":"query","required":false,"description":"Only events overlapping on or after this date (`Y-m-d`).","schema":{"type":"string","format":"date"},"example":"2026-07-01"},{"name":"filter[to]","in":"query","required":false,"description":"Only events overlapping on or before this date (`Y-m-d`).","schema":{"type":"string","format":"date"},"example":"2026-07-31"}],"responses":{"200":{"description":"The company home office calendar. Flat array, not wrapped in data, not paginated.","content":{"application\/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"employee_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"},"employee_name":{"type":["string","null"],"example":"Jane Smith"},"department_id":{"type":["string","null"],"format":"uuid","description":"Department of the employee's active contract; null when none.","example":"550e8400-e29b-41d4-a716-446655440042"},"type":{"type":"string","enum":["home_office"],"example":"home_office"},"sub_type":{"type":["string","null"],"example":null},"status":{"type":"string","enum":["pending","approved","pending_removal"],"example":"approved"},"start":{"type":"string","format":"date","example":"2026-07-07"},"end":{"type":"string","format":"date","example":"2026-07-07"},"total_seconds":{"type":"integer","description":"Total booked time across all days, in seconds.","example":28800},"days":{"type":"array","description":"Every entry of the booking's raw per-day map. Home office is one row per date, so this normally holds a single day. `working_day_details` below is the same breakdown with any non-working day dropped and the half-day hours resolved; both are returned, and this one is unchanged.\n","items":{"type":"object","properties":{"date":{"type":"string","format":"date","example":"2026-07-07"},"seconds":{"type":"integer","example":28800}}}},"working_days":{"type":"number","description":"How long the booking is, in working days the employee actually consumes, each measured against that employee's own scheduled day. A part-timer's 4h day counts as 1, while 4h out of an 8h day counts as 0.5. Home office is one whole day per row, so this is normally 1. Whole counts serialize without a fractional part (1, not 1.0), so decode this as a float rather than an integer.\n","example":1},"workshift_seconds_per_day":{"type":"integer","description":"What one full working day is worth for this employee, in seconds: 28800 on a standard 8h shift, 14400 for somebody contracted to 4h days. Use it instead of assuming 8h. 0 when no contract or work shift resolves, which should be read as unknown.\n","example":28800},"is_half_day":{"type":"boolean","description":"True when either end of the booking is a half day. Normally false for home office, which is booked as whole days.\n","example":false},"starts_half_day":{"type":"boolean","description":"True when the first day is a half day: worked that morning, then away.","example":false},"ends_half_day":{"type":"boolean","description":"True when the last day is a half day. On a single-day booking this and `starts_half_day` are both true.\n","example":false},"start_time":{"type":["string","null"],"description":"Local wall-clock hour (HH:MM) the day begins on a half-day start, null otherwise. Taken from the booking's own stored time when it has one, else the tenant's configured AM\/PM split (default 12:00).\n","example":null},"end_time":{"type":["string","null"],"description":"Local wall-clock hour (HH:MM) the day ends on a half-day end, null otherwise. Same source as `start_time`.\n","example":null},"working_day_details":{"type":"array","description":"Per-day breakdown holding working days only, ascending by date, with the half-day verdict and hours resolved per day.\n","items":{"type":"object","properties":{"date":{"type":"string","format":"date","example":"2026-07-07"},"seconds":{"type":"integer","description":"Seconds booked off that day, scaled to the employee's own day.","example":28800},"is_half_day":{"type":"boolean","description":"True when this day's seconds fall short of `workshift_seconds_per_day` by more than 900 (a tolerance for lunch and rounding).\n","example":false},"start_time":{"type":["string","null"],"description":"HH:MM; non-null only on a half-day first day.","example":null},"end_time":{"type":["string","null"],"description":"HH:MM; non-null only on a half-day last day.","example":null}}}}}}},"examples":{"twoSeparateDays":{"summary":"Two home office days, one row each","description":"Home office is stored one row per date, so each entry is a single whole day and `working_days` is 1.\n","value":[{"id":"550e8400-e29b-41d4-a716-446655440050","employee_id":"550e8400-e29b-41d4-a716-446655440001","employee_name":"Jane Smith","department_id":"550e8400-e29b-41d4-a716-446655440042","type":"home_office","sub_type":null,"status":"approved","start":"2026-08-04","end":"2026-08-04","total_seconds":28800,"days":[{"date":"2026-08-04","seconds":28800}],"working_days":1,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-04","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}]},{"id":"550e8400-e29b-41d4-a716-446655440051","employee_id":"550e8400-e29b-41d4-a716-446655440001","employee_name":"Jane Smith","department_id":"550e8400-e29b-41d4-a716-446655440042","type":"home_office","sub_type":null,"status":"pending","start":"2026-08-06","end":"2026-08-06","total_seconds":28800,"days":[{"date":"2026-08-06","seconds":28800}],"working_days":1,"workshift_seconds_per_day":28800,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-06","seconds":28800,"is_half_day":false,"start_time":null,"end_time":null}]}]},"partTimer":{"summary":"A part-timer on 4h days","description":"`workshift_seconds_per_day` is 14400, so 14400 is a WHOLE day here and `is_half_day` stays false.\n","value":[{"id":"550e8400-e29b-41d4-a716-446655440052","employee_id":"550e8400-e29b-41d4-a716-446655440005","employee_name":"Sam Lee","department_id":null,"type":"home_office","sub_type":null,"status":"approved","start":"2026-08-05","end":"2026-08-05","total_seconds":14400,"days":[{"date":"2026-08-05","seconds":14400}],"working_days":1,"workshift_seconds_per_day":14400,"is_half_day":false,"starts_half_day":false,"ends_half_day":false,"start_time":null,"end_time":null,"working_day_details":[{"date":"2026-08-05","seconds":14400,"is_half_day":false,"start_time":null,"end_time":null}]}]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller belongs to another tenant, has no employee record, or has no active company."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/corrections":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCorrections"],"summary":"List timepoint corrections for the tenant (user)","operationId":"tempusListCorrections","description":"Returns a paginated list of Tempus time point corrections for the given\nPbx (tenant). Results can be filtered by correction status and by the\ngroups the requesting employee belongs to, sorted by creation time, and\nexpanded with optional related data through the `include` parameter.\n\nEach item is serialized by the `CorrectionListResource`. The response uses\nthe standard Laravel pagination envelope: a `data` array of corrections plus\n`links` and `meta` objects.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[status]","in":"query","required":false,"description":"Restrict results to corrections in the given lifecycle states. Accepts a\nrepeated array parameter or a single comma-separated string.\n","schema":{"type":"array","items":{"type":"string","enum":["pending","accepted","rejected","canceled","rejected_closed"]}},"example":["pending"]},{"name":"filter[group_id]","in":"query","required":false,"description":"Restrict results to corrections whose requesting employee belongs to one\nof the given group identifiers. Accepts a repeated array parameter or a\nsingle comma-separated string of UUIDs.\n","schema":{"type":"array","items":{"type":"string","format":"uuid"}},"example":["550e8400-e29b-41d4-a716-446655440010"]},{"name":"sort","in":"query","required":false,"description":"Sort order by creation time. `create_time` is ascending, `-create_time`\nis descending. Defaults to `-create_time`.\n","schema":{"type":"string","enum":["create_time","-create_time"]},"example":"-create_time"},{"name":"include","in":"query","required":false,"description":"Comma-separated list of optional expansions to include on each\ncorrection. Allowed values are `requesterExt`, `newStatus`, and\n`oldStatus`. Unknown values are ignored.\n","schema":{"type":"string"},"example":"requesterExt,newStatus"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page (1-100). Defaults to 15.","schema":{"type":"integer","minimum":1,"maximum":100},"example":15}],"responses":{"200":{"description":"Paginated list of corrections.","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusCorrectionList"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not authorized for this tenant (the request\nfails the FormRequest authorization check).\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/calendar":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCalendar"],"summary":"Employee calendar for the logged-in user","operationId":"tempusGetUserCalendar","description":"Returns the data behind the Tempus \"Employee Calendar\" page for the\n**logged-in user**, for a single year: the summary block, the per-company\nrights breakdown (`details`), contract periods, and a fully-classified\nday-by-day `year_calendar`. Plain data only: no colours, icons or theme;\nthe client owns presentation.\n\nThe employee is resolved from the Sanctum token; there is no employee\nparameter and a caller can only ever read their own calendar. The only\ninput is the `year` (bounded to the employee's contract history through\nnext year).\n\nPer-day `type` merge priority (highest first): `no_contract` >\n`special_holiday` > transaction (non-home-office) > `public_holiday` >\n`weekend` > `work`. Home office is an orthogonal flag, never the winning\ntype.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"year","in":"query","required":false,"description":"Calendar year to return. Must fall within the employee's\n`[minYear, maxYear]` bounds (earliest contract year \u2026 current year + 1).\nDefaults to the current year. Out-of-range values return 422.\n","schema":{"type":"integer"},"example":2026}],"responses":{"200":{"description":"The employee's calendar for the requested year.","content":{"application\/json":{"schema":{"type":"object","description":"Employee Calendar payload for one year, as plain presentation-free data:\nsummary block, per-company rights breakdown (details), and a day-by-day\nyear calendar covering every date. Scoped to the logged-in user (the employee\nis resolved from the token), so it carries no employee identity, no colours,\nand no theme.\n","required":["year","year_bounds","summary","details","contract_periods","daily_expected_seconds","year_calendar"],"properties":{"year":{"type":"integer","example":2026},"year_bounds":{"type":"object","description":"Selectable year range for the year filter (earliest contract year through next year).","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"example":{"min":2023,"max":2027}},"summary":{"type":"object","description":"Aggregate rights\/taken\/remaining for the year.","properties":{"totals":{"type":"object","description":"Aggregate seconds for the year.","properties":{"rights":{"type":"integer"},"taken":{"type":"integer"},"remaining":{"type":"integer"},"compensatory":{"type":"integer"},"available":{"type":"integer"}}},"cards":{"type":"array","description":"The headline figures shown as summary cards.","items":{"type":"object","properties":{"key":{"type":"string","enum":["rights","taken","remaining_rights","compensatory_balance","possible"]},"title":{"type":["string","null"]},"value":{"type":["string","null"],"description":"Human display (days or hours), e.g. \"26 days\"."},"raw_seconds":{"type":"integer"},"percentage":{"type":["number","null"]},"warning":{"type":"boolean","description":"True when the value fell back to an 8h\/day assumption (no workshift)."},"comment":{"type":["string","null"]}}}},"handle_compensatory_balance":{"type":"boolean"},"workshift_missing":{"type":"boolean","description":"True when no contract\/workshift is set, so days-vs-hours fell back to 8h."}}},"details":{"type":"object","description":"Per-company rights breakdown for the whole year.","properties":{"total_seconds":{"type":"integer"},"total_display":{"type":"string"},"companies":{"type":"array","items":{"type":"object","properties":{"company_id":{"type":["string","null"],"format":"uuid"},"company":{"type":["string","null"]},"period_label":{"type":["string","null"]},"periods":{"type":"array","items":{"type":"object","properties":{"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"}}}},"show_period":{"type":"boolean"},"switched_on":{"type":["string","null"]},"subtotal_seconds":{"type":"integer"},"subtotal_display":{"type":["string","null"]},"rows":{"type":"array","items":{"type":"object","properties":{"type":{"type":["string","null"],"description":"Human label of the holiday pool."},"type_key":{"type":["string","null"],"description":"Machine key, e.g. legal, age, public_holiday."},"description":{"type":["string","null"]},"rights_seconds":{"type":"integer"},"rights_display":{"type":["string","null"]}}}}}}}}},"contract_periods":{"type":"array","description":"The employee's contract periods clamped to the year.","items":{"type":"object","properties":{"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"}}}},"daily_expected_seconds":{"type":"integer","description":"Expected working seconds per day for the year (weekly time \u00f7 5).","example":28800},"year_calendar":{"type":"object","description":"Every date of the year (YYYY-MM-DD keys) mapped to its classified day.\n","additionalProperties":{"type":"object","description":"A single classified calendar day.","properties":{"date":{"type":"string","format":"date"},"weekday":{"type":"integer","description":"ISO weekday, 1 (Mon) \u2026 7 (Sun)."},"is_weekend":{"type":"boolean"},"in_contract":{"type":"boolean"},"type":{"type":"string","description":"Winning classification, decided with priority (highest first):\nno_contract > special_holiday > transaction (non-home-office) >\npublic_holiday > weekend > work.\n","enum":["work","weekend","no_contract","public_holiday","special_holiday","legal","absence","illness","special"]},"status":{"type":["string","null"],"description":"Set for transaction days only.","enum":["approved","pending","pending_removal","rejected","cancelled","removed",null]},"sub_type":{"type":["string","null"]},"sub_type_label":{"type":["string","null"],"description":"Human label, e.g. \"Sick child\"."},"note":{"type":["string","null"]},"start_time":{"type":["string","null"]},"end_time":{"type":["string","null"]},"is_first_day":{"type":["boolean","null"]},"is_last_day":{"type":["boolean","null"]},"is_single_day":{"type":["boolean","null"]},"seconds":{"type":["integer","null"],"description":"Seconds booked this day (transaction days)."},"expected_seconds":{"type":"integer"},"home_office":{"type":["object","null"],"description":"Home office flag (present regardless of the base type).","properties":{"present":{"type":"boolean"},"status":{"type":"string"}}},"public_holiday":{"type":["object","null"],"properties":{"name":{"type":["string","null"]}}},"special_holiday":{"type":["object","null"],"properties":{"title":{"type":["string","null"]}}},"transactions":{"type":"array","description":"All bookings on this day (for multi-event days).","items":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid"},"type":{"type":["string","null"]},"sub_type":{"type":["string","null"]},"status":{"type":["string","null"]},"seconds":{"type":"integer"},"start_time":{"type":["string","null"]},"end_time":{"type":["string","null"]},"note":{"type":["string","null"]}}}}}}}}}}}},"401":{"description":"Unauthenticated."},"403":{"description":"The authenticated user has no employee record in this Pbx."},"422":{"description":"The requested year is outside the employee's allowed range."}}}},"\/{pbx_id}\/validators":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"List all validators in the tenant","operationId":"tempusListValidators","description":"Every validator in the tenant (an employee named on any validator rule),\nwith the per-module permissions they hold and the lightweight list of\nemployees they validate (the union across their rules' company \/ department \/\nemployees scope). Readable by any authenticated user in the tenant.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"The validators in the tenant.","content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["validator","permissions","employees"],"properties":{"validator":{"type":"object","properties":{"employee_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"}}},"permissions":{"type":"object","description":"Which validator modules the caller may act on for this employee.","properties":{"holiday_requests":{"type":"boolean"},"home_office_requests":{"type":"boolean"},"time_point_corrections_requests":{"type":"boolean"},"schedules_management":{"type":"boolean"}}},"employees":{"type":"array","description":"Lightweight list of the employees this validator may consult.","items":{"type":"object","properties":{"employee_id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}}}}}}},"example":{"data":[{"validator":{"employee_id":"550e8400-e29b-41d4-a716-446655440000","user_id":"550e8400-e29b-41d4-a716-446655440001","name":"Jane Smith"},"permissions":{"holiday_requests":true,"home_office_requests":true,"time_point_corrections_requests":false,"schedules_management":false},"employees":[{"employee_id":"550e8400-e29b-41d4-a716-446655440010","name":"John Doe"},{"employee_id":"550e8400-e29b-41d4-a716-446655440011","name":"Mary Jones"}]}]}}}},"401":{"description":"Unauthenticated."},"403":{"description":"The caller does not belong to this tenant."}}}},"\/{pbx_id}\/validator\/employees":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"Employees the logged-in validator can validate","operationId":"tempusListValidatorEmployees","description":"Returns the employees the logged-in user (a validator) is allowed to\nvalidate (the union across all validator modules), each with identity, the\nactive contract, and a per-module capability map. Access is rule-based\n(see the \"Validators & Managers\" rules). Matricule is never returned.\n\nOptional filters narrow the list by the employee's active-contract company or\ndepartment, or to a single employee. The dropdown values (the companies \/\ndepartments \/ employees in scope) come from the caller's user-profile\n`validator` block.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[company_id]","in":"query","required":false,"description":"Keep only employees whose active contract is in this company.","schema":{"type":"string","format":"uuid"}},{"name":"filter[department_id]","in":"query","required":false,"description":"Keep only employees whose active contract is in this department.","schema":{"type":"string","format":"uuid"}},{"name":"filter[employee_id]","in":"query","required":false,"description":"Keep only this employee (when in scope).","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The employees in the validator's scope.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"employee_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440010"},"user_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440011"},"first_name":{"type":["string","null"],"example":"John"},"last_name":{"type":["string","null"],"example":"Doe"},"email":{"type":["string","null"],"example":"john.doe@example.com"},"extension_id":{"type":["string","null"],"format":"uuid","example":"550e8400-e29b-41d4-a716-446655440020"},"is_active":{"type":"boolean","example":true},"contract":{"type":["object","null"],"description":"The employee's active contract, or null when none is active.","properties":{"start_date":{"type":["string","null"],"format":"date"},"end_date":{"type":["string","null"],"format":"date"},"weekly_expected_working_time_seconds":{"type":"integer"},"weekly_expected_working_time":{"type":"string","description":"HH:MM."},"participation":{"type":["number","null"],"description":"FTE fraction, e.g. 100 or 80."},"job_title":{"type":["string","null"]},"contract_type":{"type":["string","null"]},"company_id":{"type":["string","null"],"format":"uuid"},"company":{"type":["string","null"]},"department_id":{"type":["string","null"],"format":"uuid"},"department":{"type":["string","null"]},"compensatory_balance_seconds":{"type":"integer"},"ho_balance_seconds":{"type":"integer"}}},"modules":{"type":"object","description":"Which validator modules the caller may act on for this employee.","properties":{"holiday_requests":{"type":"boolean"},"home_office_requests":{"type":"boolean"},"time_point_corrections_requests":{"type":"boolean"},"schedules_management":{"type":"boolean"}}}}}}}}}}},"401":{"description":"Unauthenticated."},"403":{"description":"The caller has no employee record in this tenant."},"422":{"description":"A filter value is not a valid UUID."}}}},"\/{pbx_id}\/validator\/{employee_id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"Validator-scoped employee profile","operationId":"tempusGetValidatorEmployeeProfile","description":"Full profile of one employee as a validator sees it: identity, active\ncontract, active workshift, work hours (worked vs required, overtime on\nbusiness vs off days), legal-holiday balance, and leave \/ home-office \/\ncorrection history for the range. Returns `403` unless the target employee\nis within the caller's validator scope. Matricule is never returned.\nTransaction\/correction `status` values are the raw ledger values.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"filter[from]","in":"query","required":false,"description":"Y-m-d. Defaults to the start of the current month. Range max 100 days.","schema":{"type":"string","format":"date"}},{"name":"filter[to]","in":"query","required":false,"description":"Y-m-d. Defaults to today.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"The employee's validator-facing profile.","content":{"application\/json":{"schema":{"type":"object","properties":{"employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"email":{"type":["string","null"]},"is_active":{"type":"boolean"}}},"contract":{"type":["object","null"],"description":"The employee's active contract, or null when none is active.","properties":{"start_date":{"type":["string","null"],"format":"date"},"end_date":{"type":["string","null"],"format":"date"},"weekly_expected_working_time_seconds":{"type":"integer"},"weekly_expected_working_time":{"type":"string","description":"HH:MM."},"participation":{"type":["number","null"],"description":"FTE fraction, e.g. 100 or 80."},"job_title":{"type":["string","null"]},"contract_type":{"type":["string","null"]},"company_id":{"type":["string","null"],"format":"uuid"},"company":{"type":["string","null"]},"department_id":{"type":["string","null"],"format":"uuid"},"department":{"type":["string","null"]},"compensatory_balance_seconds":{"type":"integer"},"ho_balance_seconds":{"type":"integer"}}},"workshift":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":["string","null"]},"detail":{"type":["string","null"]},"weekly_seconds":{"type":"integer"},"weekly":{"type":"string","description":"HH:MM."},"working_hours":{"type":"object","description":"Seconds per weekday (mon..sun).","additionalProperties":{"type":"integer"}},"assignment":{"type":"object","properties":{"start_date":{"type":["string","null"],"format":"date"},"end_date":{"type":["string","null"],"format":"date"},"is_default":{"type":"boolean"}}}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},"work_hours":{"type":"object","description":"Keyed by week-start date (Monday) plus a `summary` key. Each\nbucket: totalWorkedTime, requiredWorkedTime,\nbusinessDaysWorkedTime, nonWorkingDaysWorkedTime (HH:MM:SS),\neach mirrored by a signed `<field>Seconds` integer, plus hasOvertime\nand minWorkTimeReached. The overtime figures are balances and\ngo negative for a week under the required time, so the weekly\nbuckets sum to `summary`. Days after today are excluded.\n","additionalProperties":{"type":"object"}},"holiday_balance":{"type":"object","properties":{"year":{"type":"integer"},"rights_seconds":{"type":"integer"},"taken_seconds":{"type":"integer"},"remaining_seconds":{"type":"integer"},"compensatory_seconds":{"type":"integer"},"available_seconds":{"type":"integer"}}},"leave":{"type":"array","items":{"type":"object","description":"A leave or home-office request overlapping the range.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":["string","null"],"description":"legal | absence | illness | special | home_office."},"sub_type":{"type":["string","null"]},"status":{"type":["string","null"],"description":"Raw ledger status.","enum":["pending","approved","rejected","cancelled","pending_removal","removed",null]},"start":{"type":["string","null"],"format":"date-time"},"end":{"type":["string","null"],"format":"date-time"},"requested_seconds":{"type":"integer"},"comment":{"type":["string","null"]},"created":{"type":["string","null"],"format":"date-time"}}}},"home_office":{"type":"array","items":{"type":"object","description":"A leave or home-office request overlapping the range.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":["string","null"],"description":"legal | absence | illness | special | home_office."},"sub_type":{"type":["string","null"]},"status":{"type":["string","null"],"description":"Raw ledger status.","enum":["pending","approved","rejected","cancelled","pending_removal","removed",null]},"start":{"type":["string","null"],"format":"date-time"},"end":{"type":["string","null"],"format":"date-time"},"requested_seconds":{"type":"integer"},"comment":{"type":["string","null"]},"created":{"type":["string","null"],"format":"date-time"}}}},"corrections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":["string","null"]},"timepoint_id":{"type":["string","null"],"format":"uuid"},"old_status_id":{"type":["string","null"],"format":"uuid"},"new_status_id":{"type":["string","null"],"format":"uuid"},"old_time":{"type":["string","null"],"format":"date-time"},"new_time":{"type":["string","null"],"format":"date-time"},"correction_comment":{"type":["string","null"]},"new_comment":{"type":["string","null"]},"created":{"type":["string","null"],"format":"date-time"}}}},"modules":{"type":"object","description":"Which validator modules the caller may act on for this employee.","properties":{"holiday_requests":{"type":"boolean"},"home_office_requests":{"type":"boolean"},"time_point_corrections_requests":{"type":"boolean"},"schedules_management":{"type":"boolean"}}}}}}}},"401":{"description":"Unauthenticated."},"403":{"description":"Caller has no employee record, or the employee is not in the caller's scope."},"422":{"description":"Bad date format or range exceeds 100 days."}}}},"\/{pbx_id}\/user\/{employee_id}\/corrections":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCorrections"],"summary":"List timepoint corrections for an employee (user)","operationId":"tempusListUserCorrections","description":"Returns a paginated list of Tempus time point corrections belonging to a\nsingle employee within the given Pbx (tenant), optionally filtered by\ncorrection status and ordered by creation time (newest first).\n\nEach item is serialized by the `CorrectionResource`. The response uses the\nstandard Laravel pagination envelope: a `data` array of corrections plus\n`links` and `meta` objects.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the Tempus employee whose corrections are listed.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"},{"name":"filter[status]","in":"query","required":false,"description":"Restrict results to corrections in the given lifecycle states. Accepts a\nrepeated array parameter or a single comma-separated string.\n","schema":{"type":"array","items":{"type":"string","enum":["pending","accepted","rejected","canceled","rejected_closed"]}},"example":["pending"]},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page (1-100). Defaults to 15.","schema":{"type":"integer","minimum":1,"maximum":100},"example":15}],"responses":{"200":{"description":"Paginated list of the employee's corrections.","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusCorrection"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not authorized for this employee or tenant\n(the request fails the FormRequest authorization check).\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusCorrections"],"summary":"Create a timepoint correction for an employee, edit alias (user)","operationId":"tempusCreateUserCorrection","description":"Back-compat alias of `POST ...\/corrections\/edit`. Prefer the explicit\nintent endpoints: `\/corrections\/add` (add a missing timepoint),\n`\/corrections\/edit` (amend an existing one), `\/corrections\/delete` (remove\none).\n\nCreates a pending Tempus time point correction for the authenticated\nemployee. A correction always amends an **existing** time point, so\n`timepoint_id` is **required** and must reference one of the employee's own\ntime points in this tenant. On acceptance the referenced time point is\nupdated in place (no duplicate). A `null` `new_time` requests removal of\nthat time point.\n\nAny earlier pending correction for the same `timepoint_id` is automatically\ncanceled before the new one is created. Pending validator approvals are\ngenerated after the correction is persisted.\n\nThe created correction is returned as a single object serialized by the\n`StoreUserCorrectionResource` (not wrapped in a `data` envelope). Server-set\nfields such as `pbx_id`, `employee_id`, the resolved old values, and\n`status` are not accepted in the request body.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the Tempus employee the correction is created for (must match the authenticated user's own employee).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","description":"Correction payload. Amends the existing time point referenced by\n`timepoint_id` (required).\n","required":["timepoint_id"],"properties":{"timepoint_id":{"type":"string","format":"uuid","description":"Identifier of the existing time point to correct. **Required.**\nMust reference a time point in this tenant that belongs to the\nauthenticated employee's own user.\n","example":"550e8400-e29b-41d4-a716-446655440002"},"new_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus status to apply. Must reference a status\nin the same tenant. Optional.\n","example":"550e8400-e29b-41d4-a716-446655440004"},"new_sub_status_id":{"type":["string","null"],"format":"uuid","description":"Identifier of the Tempus sub-status to apply. Must reference a\nsub-status in the same tenant. Optional.\n","example":"550e8400-e29b-41d4-a716-446655440005"},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Request that the time point be moved to a different location.\n\nVerified when the request is raised, by the same rule the live\nchange-status endpoint applies: the location must belong to this\ntenant and be enabled for presence status. Anything else is a\n422, so a correction cannot reach a location a normal punch would\nhave been refused.\n\nUnlike `new_status_id` this does NOT default to the time point's\ncurrent value. Omitting it (or sending null) means the correction\ndoes not touch the location, and acceptance leaves it exactly as\nit is. There is deliberately no way to clear a location through a\ncorrection: on the stored row, null cannot be told apart from\n\"no location change was requested\".\n","example":"550e8400-e29b-41d4-a716-446655440010"},"new_time":{"type":["string","null"],"description":"Requested timestamp for the corrected entry, in `Y-m-d H:i:s`\nformat. Optional. `null` requests removal of the time point.\n","example":"2024-03-01 08:30:00"},"correction_comment":{"type":["string","null"],"description":"Free-form justification for the correction.","example":"Forgot to clock in after lunch break."},"new_comment":{"type":["string","null"],"description":"Comment to apply to the corrected or newly created time point.","example":"Corrected start time per manager approval."}}},"example":{"timepoint_id":"550e8400-e29b-41d4-a716-446655440002","new_status_id":"550e8400-e29b-41d4-a716-446655440004","new_location_id":"550e8400-e29b-41d4-a716-446655440010","new_time":"2024-03-01 08:30:00","correction_comment":"Forgot to clock in after lunch break."}}}},"responses":{"201":{"description":"The created correction.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not authorized for this employee or tenant, or\nhas no linked employee record (the request fails authorization).\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/corrections\/add":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusCorrections"],"summary":"Add-a-missing-timepoint correction (user)","operationId":"tempusAddUserCorrection","description":"Creates a pending correction that requests a BRAND-NEW timepoint: there is\nno existing timepoint, so `timepoint_id` must be omitted. On validator\nacceptance a timepoint is created (never a duplicate). Self-scoped: the\nauthenticated user must be the `{employee_id}`. Any prior pending \"add\"\ncorrection by this employee is auto-canceled first.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["new_status_id","new_time"],"properties":{"new_status_id":{"type":"string","format":"uuid","description":"Status for the new timepoint. Must exist in this tenant. Required."},"new_time":{"type":"string","description":"Timestamp for the new timepoint, `Y-m-d H:i:s`. Required.","example":"2026-03-02 08:30:00"},"new_sub_status_id":{"type":["string","null"],"format":"uuid"},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Location the new timepoint should be recorded at. Optional; omit\nor send null for no location.\n\nVerified when the request is raised, by the same rule the live\nchange-status endpoint applies: the location must belong to this\ntenant and be enabled for presence status. Anything else is a\n422, so a correction cannot reach a location a normal punch would\nhave been refused.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"correction_comment":{"type":["string","null"]},"new_comment":{"type":["string","null"]}}},"example":{"new_status_id":"550e8400-e29b-41d4-a716-446655440004","new_time":"2026-03-02 08:30:00","new_location_id":"550e8400-e29b-41d4-a716-446655440010","correction_comment":"Forgot to clock in."}}}},"responses":{"201":{"description":"The created (pending) correction.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Not authorized for this employee\/tenant, or no linked employee record."},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/corrections\/edit":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusCorrections"],"summary":"Edit-an-existing-timepoint correction (user)","operationId":"tempusEditUserCorrection","description":"Creates a pending correction that amends an EXISTING timepoint.\n`timepoint_id` is required and must be one of the requesting employee's own\ntimepoints. On validator acceptance the timepoint is updated in place, with no\nduplicate. `new_time` is optional; if omitted it defaults to the timepoint's\ncurrent time (so a status-only edit is never read as a removal). Base\n`POST ...\/corrections` (no suffix) is a back-compat alias of this endpoint.\nAny prior pending correction for the same timepoint is auto-canceled first.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["timepoint_id"],"properties":{"timepoint_id":{"type":"string","format":"uuid","description":"The existing timepoint to edit. Must belong to the authenticated employee's own user. Required."},"new_time":{"type":["string","null"],"description":"New timestamp, `Y-m-d H:i:s`. Optional; defaults to the timepoint's current time.","example":"2026-03-02 08:00:00"},"new_status_id":{"type":["string","null"],"format":"uuid"},"new_sub_status_id":{"type":["string","null"],"format":"uuid"},"new_location_id":{"type":["string","null"],"format":"uuid","description":"Request that the timepoint be moved to a different location.\n\nVerified when the request is raised, by the same rule the live\nchange-status endpoint applies: the location must belong to this\ntenant and be enabled for presence status. Anything else is a\n422, so a correction cannot reach a location a normal punch would\nhave been refused.\n\nUnlike `new_status_id` this does NOT default to the timepoint's\ncurrent value. Omitting it (or sending null) means the correction\ndoes not touch the location, and acceptance leaves it exactly as\nit is. There is deliberately no way to clear a location through a\ncorrection: on the stored row, null cannot be told apart from\n\"no location change was requested\".\n","example":"550e8400-e29b-41d4-a716-446655440010"},"correction_comment":{"type":["string","null"]},"new_comment":{"type":["string","null"]}}},"example":{"timepoint_id":"550e8400-e29b-41d4-a716-446655440002","new_status_id":"550e8400-e29b-41d4-a716-446655440004","new_location_id":"550e8400-e29b-41d4-a716-446655440010","new_time":"2026-03-02 08:00:00"}}}},"responses":{"201":{"description":"The created (pending) correction.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Not authorized for this employee\/tenant, or no linked employee record."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/corrections\/delete":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusCorrections"],"summary":"Delete-a-timepoint correction (user)","operationId":"tempusDeleteUserCorrection","description":"Requests removal of an EXISTING timepoint. `timepoint_id` is required and\nmust be one of the requesting employee's own timepoints. Two outcomes:\n\n- If there is **no** pending correction for that timepoint, a pending delete\n  request is created (`201`); on validator acceptance the timepoint is\n  removed.\n- If a correction for that timepoint is **already pending**, that pending\n  request is canceled directly (`200`, no new request and no approval);\n  i.e. delete retracts the outstanding correction.\n\nSelf-scoped: the authenticated user must be the `{employee_id}`.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["timepoint_id"],"properties":{"timepoint_id":{"type":"string","format":"uuid","description":"The existing timepoint to remove. Must belong to the authenticated employee's own user. Required."},"correction_comment":{"type":["string","null"]},"new_comment":{"type":["string","null"]}}},"example":{"timepoint_id":"550e8400-e29b-41d4-a716-446655440002","correction_comment":"Wrong entry."}}}},"responses":{"201":{"description":"A pending delete correction was created.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"200":{"description":"An already-pending correction for the timepoint was canceled instead.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Not authorized for this employee\/tenant, or no linked employee record."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/corrections\/{correction_id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCorrections"],"summary":"Get a timepoint correction for an employee (user)","operationId":"tempusGetUserCorrection","description":"Returns a single Tempus time point correction belonging to the given\nemployee within the tenant. The authenticated user may only read their own\nemployee's corrections.\n\nThe correction is returned as a single object serialized by the\n`CorrectionResource` (not wrapped in a `data` envelope), with the related\ntime point, statuses, and sub-statuses eager loaded.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the Tempus employee (must match the authenticated user's own employee).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"},{"name":"correction_id","in":"path","required":true,"description":"Identifier of the correction to retrieve.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"}],"responses":{"200":{"description":"The requested correction.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no linked employee record, is requesting an\nemployee other than their own, or does not belong to the tenant.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["TempusCorrections"],"summary":"Cancel a timepoint correction for an employee (user)","operationId":"tempusUpdateUserCorrection","description":"Cancels an existing Tempus time point correction for the authenticated\nemployee. The only accepted `status` value is `canceled`.\n\nBehaviour depends on the correction's current state. A `pending` correction\nis marked `canceled` and its pending approvals are removed. An `accepted`\ncorrection cannot be undone directly; instead a new pending reversal\ncorrection (old and new values swapped) is created and returned for\nvalidation. Any other current state results in an error.\n\nThe resulting correction is returned as a single object serialized by the\n`UpdateUserCorrectionResource` (not wrapped in a `data` envelope).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"employee_id","in":"path","required":true,"description":"Identifier of the Tempus employee (must match the authenticated user's own employee).","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"},{"name":"correction_id","in":"path","required":true,"description":"Identifier of the correction to cancel.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["canceled"],"description":"Target status. Only `canceled` is accepted.","example":"canceled"}}},"example":{"status":"canceled"}}}},"responses":{"200":{"description":"The canceled correction, or the newly created pending reversal\ncorrection when the original had been accepted.\n","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusCorrection"}}}},"400":{"description":"The correction is neither pending nor accepted and therefore cannot be\ncanceled.\n"},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not authorized for this employee or tenant\n(the request fails the FormRequest authorization check).\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/corrections\/{correction_id}\/validations":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusCorrections"],"summary":"List validation decisions for a time-point correction (user)","operationId":"tempusListCorrectionValidations","description":"Returns the paginated list of validation (approval) decisions attached to a\nsingle Tempus time-point correction request. Each item is a\n`TempusCorrectionApproval` recording one validator's decision. The validator\nsummary is eager-loaded on every item. Results are wrapped in the standard\nLaravel pagination envelope (`data`, `links`, `meta`).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"correction_id","in":"path","required":true,"description":"Identifier of the Tempus time-point correction request.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440002"}},{"name":"page","in":"query","required":false,"description":"Page number of the result set.","schema":{"type":"integer","minimum":1,"example":1}},{"name":"per_page","in":"query","required":false,"description":"Number of records per page (maximum 100).","schema":{"type":"integer","minimum":1,"maximum":100,"example":15}}],"responses":{"200":{"description":"Paginated list of validation decisions for the correction.","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusCorrectionApproval"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user does not belong to the requested tenant.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusCorrections"],"summary":"Submit a validation decision for a time-point correction (user)","operationId":"tempusCreateCorrectionValidation","description":"Records the authenticated validator's decision (accepted or rejected) for a\nTempus time-point correction request, then applies the decision to the\ncorrection. If the validator already has a pending decision on this\ncorrection it is updated in place; a decision that has already been finalised\ncannot be resubmitted. The authenticated user must have a linked Tempus\nemployee record. A requester notification email is dispatched after the\ndecision is committed.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"Identifier of the Pbx (tenant).","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"correction_id","in":"path","required":true,"description":"Identifier of the Tempus time-point correction request.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440002"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["accepted","rejected"],"description":"The decision being recorded for this correction.","example":"accepted"},"comment":{"type":["string","null"],"description":"Free-form note explaining the decision. When provided and `note`\nis absent, it is used as the stored note.\n","maxLength":65535,"example":"Approved after confirming the corrected clock-in time."},"note":{"type":["string","null"],"description":"Free-form note explaining the decision.","maxLength":65535,"example":"Approved after confirming the corrected clock-in time."},"new_time":{"type":["string","null"],"format":"date-time","description":"Optional corrected time-point value to apply.","example":"2024-03-01T08:00:00+00:00"},"new_status_id":{"type":["string","null"],"format":"uuid","description":"Optional identifier of the time-point status to apply.","example":"550e8400-e29b-41d4-a716-446655440010"}}}}}},"responses":{"201":{"description":"The validation decision was recorded.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Correction validation created."}}}}}},"400":{"description":"The correction is no longer pending and cannot be validated.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This correction is no longer pending."}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user does not belong to the requested tenant or has no\nlinked Tempus employee record.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"409":{"description":"A validation decision already exists for this correction.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This correction has already been validated."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/validator\/pending-requests":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"List employees with pending absence and home office requests (user)","operationId":"tempusListValidatorPendingRequests","security":[{"bearerAuth":[]}],"description":"Returns the employees, in scope of the authenticated validator, who have\npending home office requests, absence requests, or absence removal requests\nawaiting validation. The authenticated user must be a Tempus employee in the\ngiven PBX; otherwise a 403 is returned.\n\nThe response is a hand-rolled envelope. The `data` object is keyed by the\nemployee's telephony extension id. Each value carries the optional\n`home_office`, `absence_requests`, and `absence_removals` sections, populated\nonly when the validator has scope for that module and pending records exist.\n\nThe queue is built from the approval rows addressed to the caller, so it\naccounts for approval chains: which step holds the request, watchers, and\nself-approval grants. Every request entry therefore also reports\n`can_decide_now`, `watcher`, `step`, and `awaiting`. Requests at a step below\nthe caller's are listed with `can_decide_now: false`: visible, not yet theirs\nto decide.\n\n`home_office` keeps its three date lists and adds a `requests` array, because\na home office group is one row per day and the date lists cannot say which\ndays the caller may act on.\n\nAbsence entries (`absence_requests`, `absence_removals`) also carry\n`next_availability`: when that employee is back **if this request is approved**,\nnext to what the general next-availability answer says today. Home office does\nnot \u2014 a home office day is governed by a weekly limit, not time off that moves an\navailability date.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number of the employee list to return.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":10},"description":"Number of employees to return per page.","example":10}],"responses":{"200":{"description":"OK. Employees with pending requests, keyed by extension id.","content":{"application\/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"object","description":"Object keyed by employee extension id. Each value holds the\npending request sections for that employee.\n","additionalProperties":{"type":"object","properties":{"home_office":{"type":"object","properties":{"requested_days":{"type":"array","items":{"type":"string","format":"date"}},"requested_removals":{"type":"array","items":{"type":"string","format":"date"}},"validated_dates":{"type":"array","items":{"type":"string","format":"date"}},"requests":{"type":"array","description":"One entry per home office day-row, so the chain state\ncan be read per row rather than per employee.\n","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"dates":{"type":"array","description":"The dates the request covers, read from its per-day booked map. Requests raised since that map held working days only list working days here; older ones can still include a weekend or public holiday inside the range, because those were stored as 0-second entries at the time.\n","items":{"type":"string","format":"date"}},"sub_type":{"type":["string","null"]}}},{"type":"object","description":"Where a queued request sits in its approval chain, from the point of view of the\nvalidator who asked for the queue.\n\nA request routes through a chain of steps, and only the step currently holding it\nmay decide. A validator therefore sees requests in two states: theirs to act on\nnow, and theirs to expect. Both are listed, so a validator on a later step is not\nsurprised by a request appearing from nowhere once the step below clears.\n\nRequests raised before approval chains existed carry no step: `step` is null and\n`can_decide_now` is true, because there is no ladder to wait on.\n","required":["can_decide_now","watcher","step","awaiting"],"properties":{"can_decide_now":{"type":"boolean","description":"Whether this validator may record a decision on the request right now.\nFalse while the request is at a step below theirs: the decision endpoints\nanswer 409 in that case, and a client should not offer the action.\n","example":true},"watcher":{"type":"boolean","description":"Whether this validator holds the request as a watcher rather than as a step\nvalidator. Watchers sit outside the ladder: they carry no step and, when\ngranted the power, may settle the request at any point.\n","example":false},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","description":"The validators the request is waiting on right now: those still to answer at\nthe step holding it, the caller aside. Empty when the caller is the only one\nleft to answer.\n","items":{"type":"string"},"example":["Muller Jonas"]}}}]}}}},"absence_requests":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"start_format":{"type":["string","null"]},"end_format":{"type":["string","null"]},"start":{"type":["string","null"],"format":"date"},"end":{"type":["string","null"],"format":"date"},"comment":{"type":["string","null"]},"requested_time":{"type":"string"},"next_availability":{"oneOf":[{"type":"object","description":"When an employee is next at work **if the request carrying this object goes through**,\nnext to what the general next-availability answer says today. The validator's view of a\nrequest: no second call, and no cache between the queue and the date.\n\nIt is deliberately not the same question as `GET \/user\/{employee_id}\/next-availability`:\n\n- **Anchored at the request, not at today**, so it reports the day *this* booking frees\n  rather than the next free day counting from now.\n- **Counts what has been decided plus this one request.** The base is what has been\n  signed off (accepted, plus an accepted absence somebody has asked to cancel \u2014 still\n  time off until that cancellation is approved). Other queued requests are left out:\n  they may be refused, and a date that moves because of a request this validator has not\n  seen is not one they can act on. (`current` does count every pending row \u2014 that\n  difference is intentional.)\n- **A removal reads as a reduction**, so its answer moves *earlier*, often into the past\n  (`in_past`), which is the signal that the employee is already back.\n\nAbsence, illness, special leave and legal holiday only. Home office never carries it: a\nhome office day is governed by a weekly limit, not time off that moves an availability\ndate. Neither does a request that can no longer move a date \u2014 `rejected`, `canceled` and\n`removed`.\n\n**Where it appears:** the absence lists (`\/absences`, `\/user\/{employee_id}\/absences`), the\nabsence-request reads and writes (`\/absence-requests`, `\/user\/{employee_id}\/absence-requests`\nand its `POST`\/`PUT`), `POST \/user\/{employee_id}\/absence-removal-requests`, and both\nvalidator queues (`\/validator\/pending-requests` \u2014 on each `absence_requests[]` \/\n`absence_removals[]` entry \u2014 and v2 `pending-requests\/absences`). It is **not** on the\ncancel responses (`POST ...\/absence-requests\/{id}\/cancel`), which report the outcome of an\nemployee's own action rather than something a validator is weighing up.\n\nOn the resource-backed payloads the key is **omitted** when there is nothing to say; on\nthe v1 validator queue, whose entries are built by hand, it is always present and `null`\nin that case. Both mean the same thing.\n","required":["if_approved","current"],"properties":{"if_approved":{"type":"object","description":"Availability as it would stand with this request applied.","required":["absent_from","next_available_date","next_available_at","available_now","in_past","extends_current_absence","message"],"properties":{"absent_from":{"type":["string","null"],"format":"date","description":"First day, today or later, that this request itself takes off. Null when it takes\nnothing off in the future: a removal request, or days that have all been and gone.\n","example":"2026-08-13"},"next_available_date":{"type":["string","null"],"format":"date","description":"The day the employee is back at work under this scenario. Null only when no\nworking day was found within the search horizon \u2014 an employee with no work shift,\nor one whose contract has ended.\n","example":"2026-08-17"},"next_available_at":{"type":["string","null"],"description":"Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down;\nnull when only the date is meaningful.\n","example":null},"available_now":{"type":"boolean","description":"Whether the employee is at work right now under this scenario. True together with\na future `absent_from` is the ordinary case for a request that starts later.\n","example":true},"in_past":{"type":"boolean","description":"True when `next_available_date` is already behind us, i.e. approving this would\nnot keep anybody away from now on. Render it as \"already available\" rather than as\na return date.\n","example":false},"extends_current_absence":{"type":"boolean","description":"True when this request starts on the very day the employee would otherwise have\ncome back, so it lengthens the absence already in place rather than opening a\nseparate one. False for a request with working days in between \u2014 show\n`absent_from` as well as the return date in that case, or the return date reads as\na contradiction of `available_now`.\n","example":false},"message":{"type":["string","null"],"description":"Ready-to-display line, already covering the three cases: `Available on\n2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available\n(was back on 2026-08-03)`. Show it as returned.\n","example":"Off from 2026-08-13, available on 2026-08-17"}}},"current":{"type":"object","description":"Today's general answer, unchanged \u2014 the same figure\n`GET \/user\/{employee_id}\/next-availability` returns, so the two screens never disagree.\n","required":["next_available_date","message"],"properties":{"next_available_date":{"type":["string","null"],"format":"date","description":"Next day the employee is available, counting from now. Null when they are\navailable right now.\n","example":"2026-08-12"},"message":{"type":["string","null"],"description":"Ready-to-display line, or null while the employee is available.","example":"Back on 2026-08-12"}}}},"example":{"if_approved":{"absent_from":"2026-08-13","next_available_date":"2026-08-17","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-13, available on 2026-08-17"},"current":{"next_available_date":"2026-08-12","message":"Back on 2026-08-12"}}},{"type":"null"}],"description":"When this employee is back if this request is approved, next to\nwhat the general answer says today. Always present on absence\nentries; `null` for a row that can no longer move a date.\n"},"validators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ext_id":{"type":["string","null"]},"comment":{"type":["string","null"]},"status":{"type":"string"}}}},"can_decide_now":{"type":"boolean"},"watcher":{"type":"boolean"},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","items":{"type":"string"}}}}},"absence_removals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"start_format":{"type":["string","null"]},"end_format":{"type":["string","null"]},"start":{"type":["string","null"],"format":"date"},"end":{"type":["string","null"],"format":"date"},"comment":{"type":["string","null"]},"requested_time":{"type":"string"},"next_availability":{"oneOf":[{"type":"object","description":"When an employee is next at work **if the request carrying this object goes through**,\nnext to what the general next-availability answer says today. The validator's view of a\nrequest: no second call, and no cache between the queue and the date.\n\nIt is deliberately not the same question as `GET \/user\/{employee_id}\/next-availability`:\n\n- **Anchored at the request, not at today**, so it reports the day *this* booking frees\n  rather than the next free day counting from now.\n- **Counts what has been decided plus this one request.** The base is what has been\n  signed off (accepted, plus an accepted absence somebody has asked to cancel \u2014 still\n  time off until that cancellation is approved). Other queued requests are left out:\n  they may be refused, and a date that moves because of a request this validator has not\n  seen is not one they can act on. (`current` does count every pending row \u2014 that\n  difference is intentional.)\n- **A removal reads as a reduction**, so its answer moves *earlier*, often into the past\n  (`in_past`), which is the signal that the employee is already back.\n\nAbsence, illness, special leave and legal holiday only. Home office never carries it: a\nhome office day is governed by a weekly limit, not time off that moves an availability\ndate. Neither does a request that can no longer move a date \u2014 `rejected`, `canceled` and\n`removed`.\n\n**Where it appears:** the absence lists (`\/absences`, `\/user\/{employee_id}\/absences`), the\nabsence-request reads and writes (`\/absence-requests`, `\/user\/{employee_id}\/absence-requests`\nand its `POST`\/`PUT`), `POST \/user\/{employee_id}\/absence-removal-requests`, and both\nvalidator queues (`\/validator\/pending-requests` \u2014 on each `absence_requests[]` \/\n`absence_removals[]` entry \u2014 and v2 `pending-requests\/absences`). It is **not** on the\ncancel responses (`POST ...\/absence-requests\/{id}\/cancel`), which report the outcome of an\nemployee's own action rather than something a validator is weighing up.\n\nOn the resource-backed payloads the key is **omitted** when there is nothing to say; on\nthe v1 validator queue, whose entries are built by hand, it is always present and `null`\nin that case. Both mean the same thing.\n","required":["if_approved","current"],"properties":{"if_approved":{"type":"object","description":"Availability as it would stand with this request applied.","required":["absent_from","next_available_date","next_available_at","available_now","in_past","extends_current_absence","message"],"properties":{"absent_from":{"type":["string","null"],"format":"date","description":"First day, today or later, that this request itself takes off. Null when it takes\nnothing off in the future: a removal request, or days that have all been and gone.\n","example":"2026-08-13"},"next_available_date":{"type":["string","null"],"format":"date","description":"The day the employee is back at work under this scenario. Null only when no\nworking day was found within the search horizon \u2014 an employee with no work shift,\nor one whose contract has ended.\n","example":"2026-08-17"},"next_available_at":{"type":["string","null"],"description":"Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down;\nnull when only the date is meaningful.\n","example":null},"available_now":{"type":"boolean","description":"Whether the employee is at work right now under this scenario. True together with\na future `absent_from` is the ordinary case for a request that starts later.\n","example":true},"in_past":{"type":"boolean","description":"True when `next_available_date` is already behind us, i.e. approving this would\nnot keep anybody away from now on. Render it as \"already available\" rather than as\na return date.\n","example":false},"extends_current_absence":{"type":"boolean","description":"True when this request starts on the very day the employee would otherwise have\ncome back, so it lengthens the absence already in place rather than opening a\nseparate one. False for a request with working days in between \u2014 show\n`absent_from` as well as the return date in that case, or the return date reads as\na contradiction of `available_now`.\n","example":false},"message":{"type":["string","null"],"description":"Ready-to-display line, already covering the three cases: `Available on\n2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available\n(was back on 2026-08-03)`. Show it as returned.\n","example":"Off from 2026-08-13, available on 2026-08-17"}}},"current":{"type":"object","description":"Today's general answer, unchanged \u2014 the same figure\n`GET \/user\/{employee_id}\/next-availability` returns, so the two screens never disagree.\n","required":["next_available_date","message"],"properties":{"next_available_date":{"type":["string","null"],"format":"date","description":"Next day the employee is available, counting from now. Null when they are\navailable right now.\n","example":"2026-08-12"},"message":{"type":["string","null"],"description":"Ready-to-display line, or null while the employee is available.","example":"Back on 2026-08-12"}}}},"example":{"if_approved":{"absent_from":"2026-08-13","next_available_date":"2026-08-17","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-13, available on 2026-08-17"},"current":{"next_available_date":"2026-08-12","message":"Back on 2026-08-12"}}},{"type":"null"}],"description":"When this employee is back if this request is approved, next to\nwhat the general answer says today. Always present on absence\nentries; `null` for a row that can no longer move a date.\n"},"validators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ext_id":{"type":["string","null"]},"comment":{"type":["string","null"]},"status":{"type":"string"}}}},"can_decide_now":{"type":"boolean"},"watcher":{"type":"boolean"},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","items":{"type":"string"}}}}}}}},"pagination":{"type":"object","required":["page","total_pages","total","per_page"],"properties":{"page":{"type":"integer","example":1},"total_pages":{"type":"integer","example":3},"total":{"type":"integer","example":24},"per_page":{"type":"integer","example":10}}}}},"example":{"data":{"1042":{"home_office":{"requested_days":["2024-03-04"],"requested_removals":[],"validated_dates":[],"requests":[{"id":"550e8400-e29b-41d4-a716-446655440030","dates":["2024-03-04"],"sub_type":null,"can_decide_now":true,"watcher":false,"step":{"position":1,"total":2,"name":"Team lead","status":"active","required":1,"mandatory":false},"awaiting":[]}]},"absence_requests":[{"id":"550e8400-e29b-41d4-a716-446655440010","start_format":"04 Mar 09:00","end_format":"06 Mar 18:00","start":"2024-03-04","end":"2024-03-06","comment":"Family trip","requested_time":"24h","next_availability":{"if_approved":{"absent_from":"2024-03-04","next_available_date":"2024-03-07","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2024-03-04, available on 2024-03-07"},"current":{"next_available_date":null,"message":null}},"validators":[{"id":"550e8400-e29b-41d4-a716-446655440020","ext_id":"1099","comment":null,"status":"pending"}],"can_decide_now":false,"watcher":false,"step":{"position":2,"total":2,"name":"Management","status":"pending","required":1,"mandatory":false},"awaiting":["Muller Jonas"]}],"absence_removals":[]}},"pagination":{"page":1,"total_pages":3,"total":24,"per_page":10}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user is not part of the PBX or is not a\nTempus employee in this tenant.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/validator\/pending-corrections":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"List pending time point corrections in the validator scope (user)","operationId":"tempusListValidatorPendingCorrections","security":[{"bearerAuth":[]}],"description":"Returns the pending time point correction requests raised by employees who\nfall within the authenticated validator's correction scope. The\nauthenticated user must be a Tempus employee in the given PBX; otherwise a\n403 is returned.\n\nThe response is a hand-rolled envelope: a `data` array of correction objects\nplus a `pagination` block. Each correction is serialized by the V1\n`PendingCorrectionResource`.\n\nThe queue is built from the approval rows addressed to the caller, so it\naccounts for approval chains. Each correction therefore also reports\n`can_decide_now`, `watcher`, `step`, and `awaiting`: a correction at a step\nbelow the caller's is listed with `can_decide_now: false`, visible but not yet\ntheirs to decide.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number of the corrections list to return.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":10},"description":"Number of corrections to return per page.","example":10}],"responses":{"200":{"description":"OK. Paginated list of pending corrections.","content":{"application\/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"allOf":[{"$ref":"#\/components\/schemas\/TempusPendingCorrection"},{"type":"object","description":"Where a queued request sits in its approval chain, from the point of view of the\nvalidator who asked for the queue.\n\nA request routes through a chain of steps, and only the step currently holding it\nmay decide. A validator therefore sees requests in two states: theirs to act on\nnow, and theirs to expect. Both are listed, so a validator on a later step is not\nsurprised by a request appearing from nowhere once the step below clears.\n\nRequests raised before approval chains existed carry no step: `step` is null and\n`can_decide_now` is true, because there is no ladder to wait on.\n","required":["can_decide_now","watcher","step","awaiting"],"properties":{"can_decide_now":{"type":"boolean","description":"Whether this validator may record a decision on the request right now.\nFalse while the request is at a step below theirs: the decision endpoints\nanswer 409 in that case, and a client should not offer the action.\n","example":true},"watcher":{"type":"boolean","description":"Whether this validator holds the request as a watcher rather than as a step\nvalidator. Watchers sit outside the ladder: they carry no step and, when\ngranted the power, may settle the request at any point.\n","example":false},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","description":"The validators the request is waiting on right now: those still to answer at\nthe step holding it, the caller aside. Empty when the caller is the only one\nleft to answer.\n","items":{"type":"string"},"example":["Muller Jonas"]}}}]}},"pagination":{"type":"object","required":["page","total_pages","total","per_page"],"properties":{"page":{"type":"integer","example":1},"total_pages":{"type":"integer","example":4},"total":{"type":"integer","example":38},"per_page":{"type":"integer","example":10}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user is not part of the PBX or is not a\nTempus employee in this tenant.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/validator\/pending-corrections\/{correction_id}\/details":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"Get the time points behind a pending correction (user)","operationId":"tempusGetValidatorPendingCorrectionDetails","security":[{"bearerAuth":[]}],"description":"Returns the day's time points for the employee tied to a single pending\ncorrection, giving the validator the surrounding clock events for context.\nThe correction must belong to an employee within the authenticated\nvalidator's correction scope; otherwise a 403 is returned. A 400 is returned\nwhen the correction has neither a new nor an old time, or its requester has\nno linked user.\n\nThe response is a bare array of time point objects (not wrapped in `data`),\neach serialized by the V1 `PendingCorrectionDetailsResource`.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"correction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the pending correction to inspect.","example":"550e8400-e29b-41d4-a716-446655440010"}],"responses":{"200":{"description":"OK. Time points for the correction's day.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusPendingCorrectionDetails"}}}}},"400":{"description":"Bad request. The correction has no usable date, or its requester has no\nlinked user account.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Something went wrong."}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user is not part of the PBX, is not a\nTempus employee in this tenant, or the correction is outside their\nvalidation scope.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/validator-permissions":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"Get the validator permissions for an employee (user)","operationId":"tempusGetValidatorPermissions","deprecated":true,"security":[{"bearerAuth":[]}],"description":"Deprecated: these per-module capability flags are now returned inline on the\nuser profile under the `validator.permissions` block\n(`GET \/{pbx_id}\/user\/{employee_id}\/profile`). Prefer that; this endpoint is\nkept for backward compatibility.\n\nReturns the validation capabilities the given employee holds: whether they\ncan validate absences, home office, and corrections, whether they manage\nschedules, and whether they have calendar access. The employee must belong\nto the authenticated user (their `user_id` must match the requester) and to\nthe PBX; otherwise a 403 is returned. A 404 is returned when the employee\ndoes not exist in the tenant.\n\nThe response is a flat object of booleans, not wrapped in `data`.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee.","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"OK. The employee's validation capabilities.","content":{"application\/json":{"schema":{"type":"object","required":["absence_validation","home_office_validation","correction_validation","schedules_management","calendar_access"],"properties":{"absence_validation":{"type":"boolean","description":"Whether the employee can validate absence requests."},"home_office_validation":{"type":"boolean","description":"Whether the employee can validate home office requests."},"correction_validation":{"type":"boolean","description":"Whether the employee can validate time point corrections."},"schedules_management":{"type":"boolean","description":"Whether the employee can manage schedules."},"calendar_access":{"type":"boolean","description":"Whether the employee has calendar access."}}},"example":{"absence_validation":true,"home_office_validation":true,"correction_validation":true,"schedules_management":false,"calendar_access":true}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user is not part of the PBX, or the\nemployee does not belong to the authenticated user.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This action is unauthorized."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/validator\/scope":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusValidators"],"summary":"Get the validator scope (employees the authenticated user can validate)","operationId":"getTempusValidatorScope","deprecated":true,"description":"Deprecated: the caller's validator scope is now returned inline on their user\nprofile under the `validator` block (`GET \/{pbx_id}\/user\/{employee_id}\/profile`),\nwhich carries the same per-module scope plus the consultable companies,\ndepartments and employees. Prefer that; this endpoint is kept for\nbackward compatibility.\n\nReturns the tempus validator scope identified by the path parameter. Multi-tenant scoping is\nenforced: the caller can only fetch resources within their own PBX.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant","example":"550e8400-e29b-41d4-a716-446655440000"}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"description":"OK. The response is a flat object keyed by validator module name\n(`holiday_requests`, `time_point_corrections_requests`, etc.). Each\nmodule entry says whether the authenticated user is a validator for\nthat module and lists the employees in their scope.\n","content":{"application\/json":{"schema":{"type":"object","description":"Object keyed by validator module name. NOT wrapped in `data`.\nModule names come from `ValidatorRule::MODULE_*`.\n","additionalProperties":{"type":"object","required":["enabled","targets"],"properties":{"enabled":{"type":"boolean","description":"Whether the authenticated user can validate this module"},"targets":{"type":"array","description":"Employees in scope for this module","items":{"type":"object","properties":{"user_id":{"type":["string","null"],"format":"uuid"},"employee_id":{"type":"string","format":"uuid"},"extension_id":{"type":["string","null"],"format":"uuid"}}}}}}},"example":{"holiday_requests":{"enabled":true,"targets":[{"user_id":"550e8400-e29b-41d4-a716-446655440010","employee_id":"550e8400-e29b-41d4-a716-446655440011","extension_id":"550e8400-e29b-41d4-a716-446655440012"}]},"time_point_corrections_requests":{"enabled":true,"targets":[{"user_id":"550e8400-e29b-41d4-a716-446655440020","employee_id":"550e8400-e29b-41d4-a716-446655440021","extension_id":"550e8400-e29b-41d4-a716-446655440022"}]},"home_office_requests":{"enabled":false,"targets":[]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/validator\/change-employee-status":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusValidators"],"summary":"Change a scoped employee's current status as a validator (user)","operationId":"tempusChangeValidatorEmployeeStatus","security":[{"bearerAuth":[]}],"description":"Sets the current Tempus status (and optional sub-statuses) of an employee on\nbehalf of a validator. The authenticated user must be a Tempus employee in\nthe PBX and must hold correction scope over the target employee; otherwise a\n403 is returned. A 404 is returned when no employee matches the given\n`user_id` in the tenant. A validator may assign any status, not only the ones\nin the employee's active layout.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant.","example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["user_id","status_id"],"properties":{"user_id":{"type":"string","format":"uuid","description":"UUID of the target user whose status is being changed.","example":"550e8400-e29b-41d4-a716-446655440030"},"status_id":{"type":"string","format":"uuid","description":"UUID of the Tempus status to assign.","example":"550e8400-e29b-41d4-a716-446655440031"},"sub_status_ids":{"type":"array","description":"Optional UUIDs of sub-statuses to assign. Each must belong to the\nchosen status.\n","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440032"]},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional free-form comment recorded with the change.","example":"Manual status set by validator"}}}}}},"responses":{"200":{"description":"OK. The status that was applied.","content":{"application\/json":{"schema":{"type":"object","required":["user_id","status_id","sub_status_ids"],"properties":{"user_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440030"},"status_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440031"},"sub_status_ids":{"type":"array","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440032"]}}},"example":{"user_id":"550e8400-e29b-41d4-a716-446655440030","status_id":"550e8400-e29b-41d4-a716-446655440031","sub_status_ids":["550e8400-e29b-41d4-a716-446655440032"]}}}},"400":{"description":"Bad request. The status change failed; the body carries an `errors`\narray describing the reasons.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The status change failed."},"errors":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The authenticated user is not part of the PBX, is not a\nTempus employee in this tenant, or has no correction scope over the\ntarget employee.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You are not allowed to change this employee's status."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/v2\/{pbx}\/employee\/{employee}\/profile":{"get":{"tags":["TempusProfile"],"summary":"Get your own Tempus profile (user)","operationId":"tempusV2ShowEmployeeProfile","security":[{"bearerAuth":[]}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api","description":"Tempus production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api","description":"Tempus staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api","description":"Tempus dev API server"}],"description":"The caller's own Tempus profile: their active contract, balances, home office\nsettings, preferences, and what they validate.\n\nSame payload as `GET \/tempus\/api\/v1\/{pbx_id}\/user\/{employee_id}\/profile` with one\ndifference, which is why it is versioned: the `validator` block is the v2 shape. It\nalways has the same keys (`is_validator`, `permissions`, `pending`) instead of being\nan object or null, and it drops the `companies`, `departments` and `employees` lists,\nwhich approval chains cannot produce cheaply. That roster is on\n`GET \/tempus\/api\/v1\/{pbx_id}\/validator\/employees`.\n\nThe path says `employee`, not v1's `user`: the subject is a Tempus employee record,\nand v1 passed an employee id to a segment named `user`.\n\n422 when the employee has no active contract, since almost every figure in the\npayload is derived from one.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is\nrefused with 403 rather than answered from another tenant.\n","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose queue this is. Must be the caller's own employee\nrecord: a queue is built from the approval rows addressed to one person, so another\nemployee's id is refused rather than quietly answered with your own.\n","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"OK. The employee's profile.","content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/TempusUserProfile"},{"type":"object","properties":{"validator":{"type":"object","description":"What an employee validates, and how much is waiting on them.\n\nOne shape whether or not they are a validator: `is_validator` is the flag, and a\nnon-validator gets all-false permissions with zero counts. A payload that changed shape\nfor the answer \"no\" would make that a special case at every call site.\n\nNot wrapped in `data`: one object is returned and there is no collection envelope for it\nto be consistent with.\n\nWhat it deliberately does not carry: the companies, departments and employees a\nvalidator covers, which v1's profile block did. With approval chains a validator's place\nis a position in each requester's own chain, resolved through that person's contract, so\nthat roster is not a flat set this can produce cheaply. It lives on\n`GET \/tempus\/api\/v1\/{pbx_id}\/validator\/employees`.\n","required":["is_validator","permissions","pending"],"properties":{"is_validator":{"type":"boolean","description":"Whether they hold any validator role at all, which is the signal for whether to\noffer a validator section. True when any chain that reaches somebody names them,\nas a step validator or as a watcher, for at least one request type. A chain that is\nstaffed but scoped to nobody does not count, so a half-built chain cannot light up a\nsection with nothing behind it.\n","example":true},"permissions":{"type":"object","description":"Which request types they are asked to decide.","required":["absence_requests","home_office_requests","time_point_corrections","schedule_assignment_requests"],"properties":{"absence_requests":{"type":"boolean","example":true},"home_office_requests":{"type":"boolean","example":true},"time_point_corrections":{"type":"boolean","example":false},"schedule_assignment_requests":{"type":"boolean","example":false}}},"pending":{"type":"object","description":"How many requests of each type are waiting on them right now, counted from the\napproval rows addressed to them, so it matches the queue endpoints exactly. An\nall-zero map means only that nothing is waiting today: somebody with an empty queue\nis still a validator, so gate the section on `is_validator` and use these for badges\nor to skip a part that would open empty.\n\nThe queue for each: `absence_requests` is `pending-requests\/absences`,\n`home_office_requests` is `pending-requests\/home-office`, and\n`time_point_corrections` is `pending-requests\/time-point-corrections`.\n`schedule_assignment_requests` is always 0: schedule assignment is direct\nmanagement, not a request queue.\n","required":["absence_requests","home_office_requests","time_point_corrections","schedule_assignment_requests"],"properties":{"absence_requests":{"type":"integer","example":3},"home_office_requests":{"type":"integer","example":1},"time_point_corrections":{"type":"integer","example":0},"schedule_assignment_requests":{"type":"integer","example":0}}}}}}}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The caller is outside this PBX, or asked for an employee record that is\nnot their own.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have access to this PBX."}}}}}},"404":{"description":"Not found. No such employee in this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User not found."}}}}}},"422":{"description":"Unprocessable. The employee has no active contract, so there is no profile to\nassemble.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"No active contract found for this employee."}}}}}}}}},"\/v2\/{pbx}\/employee\/{employee}\/validator":{"get":{"tags":["TempusValidators"],"summary":"Get an employee's validator role and queue counts (user)","operationId":"tempusV2ShowEmployeeValidator","security":[{"bearerAuth":[]}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api","description":"Tempus production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api","description":"Tempus staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api","description":"Tempus dev API server"}],"description":"Whether this employee holds a validator role, which request types are theirs,\nand how much is queued for them.\n\nReplaces the `validator` block of `GET \/tempus\/api\/v1\/{pbx_id}\/user\/{employee_id}\/profile`.\nThat block also carried the companies, departments and employees the validator\ncovered; with approval chains that roster is not a flat set (a validator's place\nis a position in each requester's own chain, resolved through that person's\ncontract), so it is not repeated here. For the roster use\n`GET \/tempus\/api\/v1\/{pbx_id}\/validator\/employees`; for the work itself use the\nper-type queues under `employee\/{employee}\/pending-requests\/`: `absences`,\n`home-office` and `corrections`.\n\nThe same block is on `GET \/v2\/{pbx}\/employee\/{employee}\/profile`, so a screen that\nalready fetches the profile needs no second call. This endpoint exists for the\nopposite case: deciding whether to offer a validator section is one boolean, and\nshould not require the whole profile payload.\n\nReadable for your own employee record only: asking for another employee returns\n403, since how someone else's validator duties are staffed is not theirs to read.\n\nNote the path says `employee`, not `user` as v1 did: the subject is a Tempus\nemployee record, and v1 passed an employee id to a segment named `user`.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is\nrefused with 403 rather than answered from another tenant.\n","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose queue this is. Must be the caller's own employee\nrecord: a queue is built from the approval rows addressed to one person, so another\nemployee's id is refused rather than quietly answered with your own.\n","example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"OK. Always this shape, whether or not they are a validator.","content":{"application\/json":{"schema":{"type":"object","description":"What an employee validates, and how much is waiting on them.\n\nOne shape whether or not they are a validator: `is_validator` is the flag, and a\nnon-validator gets all-false permissions with zero counts. A payload that changed shape\nfor the answer \"no\" would make that a special case at every call site.\n\nNot wrapped in `data`: one object is returned and there is no collection envelope for it\nto be consistent with.\n\nWhat it deliberately does not carry: the companies, departments and employees a\nvalidator covers, which v1's profile block did. With approval chains a validator's place\nis a position in each requester's own chain, resolved through that person's contract, so\nthat roster is not a flat set this can produce cheaply. It lives on\n`GET \/tempus\/api\/v1\/{pbx_id}\/validator\/employees`.\n","required":["is_validator","permissions","pending"],"properties":{"is_validator":{"type":"boolean","description":"Whether they hold any validator role at all, which is the signal for whether to\noffer a validator section. True when any chain that reaches somebody names them,\nas a step validator or as a watcher, for at least one request type. A chain that is\nstaffed but scoped to nobody does not count, so a half-built chain cannot light up a\nsection with nothing behind it.\n","example":true},"permissions":{"type":"object","description":"Which request types they are asked to decide.","required":["absence_requests","home_office_requests","time_point_corrections","schedule_assignment_requests"],"properties":{"absence_requests":{"type":"boolean","example":true},"home_office_requests":{"type":"boolean","example":true},"time_point_corrections":{"type":"boolean","example":false},"schedule_assignment_requests":{"type":"boolean","example":false}}},"pending":{"type":"object","description":"How many requests of each type are waiting on them right now, counted from the\napproval rows addressed to them, so it matches the queue endpoints exactly. An\nall-zero map means only that nothing is waiting today: somebody with an empty queue\nis still a validator, so gate the section on `is_validator` and use these for badges\nor to skip a part that would open empty.\n\nThe queue for each: `absence_requests` is `pending-requests\/absences`,\n`home_office_requests` is `pending-requests\/home-office`, and\n`time_point_corrections` is `pending-requests\/time-point-corrections`.\n`schedule_assignment_requests` is always 0: schedule assignment is direct\nmanagement, not a request queue.\n","required":["absence_requests","home_office_requests","time_point_corrections","schedule_assignment_requests"],"properties":{"absence_requests":{"type":"integer","example":3},"home_office_requests":{"type":"integer","example":1},"time_point_corrections":{"type":"integer","example":0},"schedule_assignment_requests":{"type":"integer","example":0}}}}},"examples":{"validator":{"summary":"Validates absences and home office, three absences waiting","value":{"is_validator":true,"permissions":{"absence_requests":true,"home_office_requests":true,"time_point_corrections":false,"schedule_assignment_requests":false},"pending":{"absence_requests":3,"home_office_requests":0,"time_point_corrections":0,"schedule_assignment_requests":0}}},"notAValidator":{"summary":"Validates nothing","value":{"is_validator":false,"permissions":{"absence_requests":false,"home_office_requests":false,"time_point_corrections":false,"schedule_assignment_requests":false},"pending":{"absence_requests":0,"home_office_requests":0,"time_point_corrections":0,"schedule_assignment_requests":0}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The caller is outside this PBX, or asked for an employee record that is\nnot their own.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have access to this PBX."}}}}}},"404":{"description":"Not found. No such employee in this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User not found."}}}}}}}}},"\/v2\/{pbx}\/employee\/{employee}\/pending-requests\/absences":{"get":{"tags":["TempusValidators"],"summary":"List the absence requests waiting on you to decide (user)","operationId":"tempusV2ListPendingAbsenceRequests","security":[{"bearerAuth":[]}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api","description":"Tempus production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api","description":"Tempus staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api","description":"Tempus dev API server"}],"description":"The absence, illness and special-leave requests this employee is asked to decide,\nnewest first, one entry per request. Requests to remove already approved days are\nincluded, marked `sub_type: removal`.\n\nRead off the approval rows addressed to them, so approval chains are honoured\nexactly as the decision endpoints honour them: which step holds the request,\nwatchers, self-approval grants, and restarts. Requests at a step below theirs are\nincluded with `can_decide_now: false`, so a validator further up a chain sees what\nis coming rather than having it appear from nowhere.\n\nYour own employee record only: another employee's id returns 403, since a queue is\nbuilt from rows addressed to one person.\n\nOne endpoint per request type, matching how the work is looked at: a screen showing\none type pages that type, instead of over-fetching a mixed feed and filtering it.\nThe sibling queues are `pending-requests\/absences`, `pending-requests\/home-office`\nand `pending-requests\/time-point-corrections`; `GET \/v2\/{pbx}\/employee\/{employee}\/validator`\nreports how many are waiting in each.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is\nrefused with 403 rather than answered from another tenant.\n","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose queue this is. Must be the caller's own employee\nrecord: a queue is built from the approval rows addressed to one person, so another\nemployee's id is refused rather than quietly answered with your own.\n","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number to return.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":10},"description":"Number of entries per page.","example":10},{"name":"filter[requester_id]","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Narrow the queue to one person who raised requests. Named `requester_id` rather than\n`employee_id` because the employee in the path is the validator: these routes have two\nemployees in play. A requester you hold no rows on yields an empty page rather than a\n403, since nothing was hidden from you.\n","example":"550e8400-e29b-41d4-a716-446655440002"}],"responses":{"200":{"description":"OK. Paginated absence requests waiting on this employee.","content":{"application\/json":{"schema":{"type":"object","description":"A page of requests waiting on one validator, one entry per request.\n\nEach entry is the v2 transaction payload plus where the caller stands in that\nrequest's approval chain. The envelope is hand-rolled (`data` plus `pagination`), not\nLaravel's paginator shape. Entries are newest first.\n","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"allOf":[{"type":"object","description":"A request stored as a Tempus transaction: absence, illness, special leave, legal\nholiday, home office, and removals of any of them.\n\nv2 of the payload. What changed from v1 and why:\n\n- **People are employees, never extensions.** v1 carried `ext_id`, a telephony\n  extension id, on a Tempus record. It was the wrong identifier for this domain (an\n  employee need not have an extension, and the field silently fell back to the\n  employee id when they did not, so it meant two different things) and it cost two\n  queries per row to produce. Everyone here is identified by `employee_id`.\n- **One identifier per thing.** v1 repeated one value as `employee_id`,\n  `requester_id` and `creator_id`, and the request id as both `id` and\n  `absence_request_id`. Also gone: `mxvp_user_id`, which was the pbx id under a name\n  from another system, and `holiday_id`, which was always null.\n- **Stored values, not translated ones.** v1 renamed `absence` to `legal` and\n  `approved` to `accepted` on the way out, so a client could not match what it read\n  against what it sent, nor against the request type names the approval chain uses.\n","required":["id","type","status","employee_id","dates","requested_time","requested_seconds"],"properties":{"id":{"type":"string","format":"uuid","description":"The request id, which the decision endpoints take. For home office this is one\nday-row: a request covering a week is stored as a row per day, each decided on\nits own.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"type":{"type":"string","enum":["absence","illness","special","legal_holiday","home_office"],"description":"The stored request type, not a renamed one.","example":"absence"},"sub_type":{"type":["string","null"],"description":"`removal` when the request asks to take back days that were already approved,\notherwise null.\n","example":null},"status":{"type":"string","enum":["pending","approved","rejected","cancelled","pending_removal"],"description":"The stored status.","example":"pending"},"employee_id":{"type":"string","format":"uuid","description":"The employee the request is for, whose balance and calendar it moves.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee":{"type":["object","null"],"description":"The same employee, by name, when the relation was loaded. Present on the validator\nqueues, absent where the endpoint does not load it.\n","properties":{"employee_id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"name":{"type":["string","null"],"example":"Muller Anna"}}},"requested_by":{"type":["object","null"],"description":"Who raised the request, when that is somebody other than the employee it is for\n(raised on their behalf). Null for the ordinary case of raising your own, so a\nclient can show provenance only when there is any.\n","properties":{"employee_id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"name":{"type":["string","null"]}}},"company_id":{"type":["string","null"],"format":"uuid"},"start":{"type":["string","null"],"format":"date-time","example":"2026-03-04T00:00:00+00:00"},"end":{"type":["string","null"],"format":"date-time","example":"2026-03-06T00:00:00+00:00"},"dates":{"type":"array","description":"The days actually asked for, which is what to read rather than the range: a\nrequest can skip days.\n","items":{"type":"string","format":"date"},"example":["2026-03-04","2026-03-05"]},"requested_time":{"type":"object","description":"Seconds asked for per day, keyed by date.","additionalProperties":{"type":"integer"},"example":{"2026-03-04":28800,"2026-03-05":28800}},"requested_seconds":{"type":"integer","description":"The sum of `requested_time`, for convenience.","example":57600},"next_availability":{"type":"object","description":"When an employee is next at work **if the request carrying this object goes through**,\nnext to what the general next-availability answer says today. The validator's view of a\nrequest: no second call, and no cache between the queue and the date.\n\nIt is deliberately not the same question as `GET \/user\/{employee_id}\/next-availability`:\n\n- **Anchored at the request, not at today**, so it reports the day *this* booking frees\n  rather than the next free day counting from now.\n- **Counts what has been decided plus this one request.** The base is what has been\n  signed off (accepted, plus an accepted absence somebody has asked to cancel \u2014 still\n  time off until that cancellation is approved). Other queued requests are left out:\n  they may be refused, and a date that moves because of a request this validator has not\n  seen is not one they can act on. (`current` does count every pending row \u2014 that\n  difference is intentional.)\n- **A removal reads as a reduction**, so its answer moves *earlier*, often into the past\n  (`in_past`), which is the signal that the employee is already back.\n\nAbsence, illness, special leave and legal holiday only. Home office never carries it: a\nhome office day is governed by a weekly limit, not time off that moves an availability\ndate. Neither does a request that can no longer move a date \u2014 `rejected`, `canceled` and\n`removed`.\n\n**Where it appears:** the absence lists (`\/absences`, `\/user\/{employee_id}\/absences`), the\nabsence-request reads and writes (`\/absence-requests`, `\/user\/{employee_id}\/absence-requests`\nand its `POST`\/`PUT`), `POST \/user\/{employee_id}\/absence-removal-requests`, and both\nvalidator queues (`\/validator\/pending-requests` \u2014 on each `absence_requests[]` \/\n`absence_removals[]` entry \u2014 and v2 `pending-requests\/absences`). It is **not** on the\ncancel responses (`POST ...\/absence-requests\/{id}\/cancel`), which report the outcome of an\nemployee's own action rather than something a validator is weighing up.\n\nOn the resource-backed payloads the key is **omitted** when there is nothing to say; on\nthe v1 validator queue, whose entries are built by hand, it is always present and `null`\nin that case. Both mean the same thing.\n","required":["if_approved","current"],"properties":{"if_approved":{"type":"object","description":"Availability as it would stand with this request applied.","required":["absent_from","next_available_date","next_available_at","available_now","in_past","extends_current_absence","message"],"properties":{"absent_from":{"type":["string","null"],"format":"date","description":"First day, today or later, that this request itself takes off. Null when it takes\nnothing off in the future: a removal request, or days that have all been and gone.\n","example":"2026-08-13"},"next_available_date":{"type":["string","null"],"format":"date","description":"The day the employee is back at work under this scenario. Null only when no\nworking day was found within the search horizon \u2014 an employee with no work shift,\nor one whose contract has ended.\n","example":"2026-08-17"},"next_available_at":{"type":["string","null"],"description":"Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down;\nnull when only the date is meaningful.\n","example":null},"available_now":{"type":"boolean","description":"Whether the employee is at work right now under this scenario. True together with\na future `absent_from` is the ordinary case for a request that starts later.\n","example":true},"in_past":{"type":"boolean","description":"True when `next_available_date` is already behind us, i.e. approving this would\nnot keep anybody away from now on. Render it as \"already available\" rather than as\na return date.\n","example":false},"extends_current_absence":{"type":"boolean","description":"True when this request starts on the very day the employee would otherwise have\ncome back, so it lengthens the absence already in place rather than opening a\nseparate one. False for a request with working days in between \u2014 show\n`absent_from` as well as the return date in that case, or the return date reads as\na contradiction of `available_now`.\n","example":false},"message":{"type":["string","null"],"description":"Ready-to-display line, already covering the three cases: `Available on\n2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available\n(was back on 2026-08-03)`. Show it as returned.\n","example":"Off from 2026-08-13, available on 2026-08-17"}}},"current":{"type":"object","description":"Today's general answer, unchanged \u2014 the same figure\n`GET \/user\/{employee_id}\/next-availability` returns, so the two screens never disagree.\n","required":["next_available_date","message"],"properties":{"next_available_date":{"type":["string","null"],"format":"date","description":"Next day the employee is available, counting from now. Null when they are\navailable right now.\n","example":"2026-08-12"},"message":{"type":["string","null"],"description":"Ready-to-display line, or null while the employee is available.","example":"Back on 2026-08-12"}}}},"example":{"if_approved":{"absent_from":"2026-08-13","next_available_date":"2026-08-17","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-13, available on 2026-08-17"},"current":{"next_available_date":"2026-08-12","message":"Back on 2026-08-12"}}},"comment":{"type":["string","null"],"description":"The requester's note.","example":"Family trip"},"created":{"type":["string","null"],"format":"date-time"},"modified":{"type":["string","null"],"format":"date-time"},"validators":{"type":"array","description":"Everyone this request asks, with their answer so far and where they sit, when the\napprovals relation was loaded. Rows superseded by a restarted chain are left out:\nthey record what a previous round asked and are not people still to answer.\n","items":{"type":"object","properties":{"employee_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string","description":"The name frozen on the row when it was written, so a validator who has since\nbeen deleted still reads correctly.\n","example":"Lemaire Farid"},"status":{"type":"string","enum":["pending","accepted","rejected"]},"comment":{"type":["string","null"]},"step_position":{"type":["integer","null"],"description":"Their rung in the chain, or null for a watcher, who sits outside the ladder.\n","example":1},"watcher":{"type":"boolean"},"mandatory":{"type":"boolean","description":"Whether their approval is required for the step to complete, whatever its\nquorum.\n"}}}}}},{"type":"object","description":"Where a queued request sits in its approval chain, from the point of view of the\nvalidator who asked for the queue.\n\nA request routes through a chain of steps, and only the step currently holding it\nmay decide. A validator therefore sees requests in two states: theirs to act on\nnow, and theirs to expect. Both are listed, so a validator on a later step is not\nsurprised by a request appearing from nowhere once the step below clears.\n\nRequests raised before approval chains existed carry no step: `step` is null and\n`can_decide_now` is true, because there is no ladder to wait on.\n","required":["can_decide_now","watcher","step","awaiting"],"properties":{"can_decide_now":{"type":"boolean","description":"Whether this validator may record a decision on the request right now.\nFalse while the request is at a step below theirs: the decision endpoints\nanswer 409 in that case, and a client should not offer the action.\n","example":true},"watcher":{"type":"boolean","description":"Whether this validator holds the request as a watcher rather than as a step\nvalidator. Watchers sit outside the ladder: they carry no step and, when\ngranted the power, may settle the request at any point.\n","example":false},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","description":"The validators the request is waiting on right now: those still to answer at\nthe step holding it, the caller aside. Empty when the caller is the only one\nleft to answer.\n","items":{"type":"string"},"example":["Muller Jonas"]}}}]}},"pagination":{"type":"object","required":["page","total_pages","total","per_page"],"properties":{"page":{"type":"integer","example":1},"total_pages":{"type":"integer","example":2},"total":{"type":"integer","example":14},"per_page":{"type":"integer","example":10}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440010","type":"absence","sub_type":null,"status":"pending","employee_id":"550e8400-e29b-41d4-a716-446655440001","employee":{"employee_id":"550e8400-e29b-41d4-a716-446655440001","first_name":"Anna","last_name":"Muller","name":"Muller Anna"},"requested_by":null,"company_id":"550e8400-e29b-41d4-a716-446655440005","start":"2026-03-04T00:00:00+00:00","end":"2026-03-06T00:00:00+00:00","dates":["2026-03-04","2026-03-05","2026-03-06"],"requested_time":{"2026-03-04":28800},"requested_seconds":86400,"next_availability":{"if_approved":{"absent_from":"2026-03-04","next_available_date":"2026-03-09","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-03-04, available on 2026-03-09"},"current":{"next_available_date":null,"message":null}},"comment":"Family trip","created":"2026-03-01T09:12:00+00:00","modified":"2026-03-01T09:12:00+00:00","validators":[{"employee_id":"550e8400-e29b-41d4-a716-446655440020","name":"Lemaire Farid","status":"pending","comment":null,"step_position":1,"watcher":false,"mandatory":false}],"can_decide_now":true,"watcher":false,"step":{"position":1,"total":2,"name":"Team lead","status":"active","required":1,"mandatory":false},"awaiting":[]}],"pagination":{"page":1,"total_pages":2,"total":14,"per_page":10}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The caller is outside this PBX, or asked for an employee record that is\nnot their own.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have access to this PBX."}}}}}},"404":{"description":"Not found. No such employee in this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User not found."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/v2\/{pbx}\/employee\/{employee}\/pending-requests\/home-office":{"get":{"tags":["TempusValidators"],"summary":"List the home office requests waiting on you to decide (user)","operationId":"tempusV2ListPendingHomeOfficeRequests","security":[{"bearerAuth":[]}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api","description":"Tempus production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api","description":"Tempus staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api","description":"Tempus dev API server"}],"description":"The home office requests this employee is asked to decide, newest first.\n\nOne entry per day-row: a home office request for a week is stored as a row per day,\neach decided on its own, and each carrying its own `id` and place in the chain. Read\n`dates` rather than `start`\/`end`. Requests to take back already approved days are\nincluded, marked `sub_type: removal`.\n\nRead off the approval rows addressed to them, so approval chains are honoured\nexactly as the decision endpoints honour them: which step holds the request,\nwatchers, self-approval grants, and restarts. Requests at a step below theirs are\nincluded with `can_decide_now: false`, so a validator further up a chain sees what\nis coming rather than having it appear from nowhere.\n\nYour own employee record only: another employee's id returns 403, since a queue is\nbuilt from rows addressed to one person.\n\nOne endpoint per request type, matching how the work is looked at: a screen showing\none type pages that type, instead of over-fetching a mixed feed and filtering it.\nThe sibling queues are `pending-requests\/absences`, `pending-requests\/home-office`\nand `pending-requests\/time-point-corrections`; `GET \/v2\/{pbx}\/employee\/{employee}\/validator`\nreports how many are waiting in each.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is\nrefused with 403 rather than answered from another tenant.\n","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose queue this is. Must be the caller's own employee\nrecord: a queue is built from the approval rows addressed to one person, so another\nemployee's id is refused rather than quietly answered with your own.\n","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number to return.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":10},"description":"Number of entries per page.","example":10},{"name":"filter[requester_id]","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Narrow the queue to one person who raised requests. Named `requester_id` rather than\n`employee_id` because the employee in the path is the validator: these routes have two\nemployees in play. A requester you hold no rows on yields an empty page rather than a\n403, since nothing was hidden from you.\n","example":"550e8400-e29b-41d4-a716-446655440002"}],"responses":{"200":{"description":"OK. Paginated home office day-rows waiting on this employee.","content":{"application\/json":{"schema":{"type":"object","description":"A page of requests waiting on one validator, one entry per request.\n\nEach entry is the v2 transaction payload plus where the caller stands in that\nrequest's approval chain. The envelope is hand-rolled (`data` plus `pagination`), not\nLaravel's paginator shape. Entries are newest first.\n","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"allOf":[{"type":"object","description":"A request stored as a Tempus transaction: absence, illness, special leave, legal\nholiday, home office, and removals of any of them.\n\nv2 of the payload. What changed from v1 and why:\n\n- **People are employees, never extensions.** v1 carried `ext_id`, a telephony\n  extension id, on a Tempus record. It was the wrong identifier for this domain (an\n  employee need not have an extension, and the field silently fell back to the\n  employee id when they did not, so it meant two different things) and it cost two\n  queries per row to produce. Everyone here is identified by `employee_id`.\n- **One identifier per thing.** v1 repeated one value as `employee_id`,\n  `requester_id` and `creator_id`, and the request id as both `id` and\n  `absence_request_id`. Also gone: `mxvp_user_id`, which was the pbx id under a name\n  from another system, and `holiday_id`, which was always null.\n- **Stored values, not translated ones.** v1 renamed `absence` to `legal` and\n  `approved` to `accepted` on the way out, so a client could not match what it read\n  against what it sent, nor against the request type names the approval chain uses.\n","required":["id","type","status","employee_id","dates","requested_time","requested_seconds"],"properties":{"id":{"type":"string","format":"uuid","description":"The request id, which the decision endpoints take. For home office this is one\nday-row: a request covering a week is stored as a row per day, each decided on\nits own.\n","example":"550e8400-e29b-41d4-a716-446655440010"},"type":{"type":"string","enum":["absence","illness","special","legal_holiday","home_office"],"description":"The stored request type, not a renamed one.","example":"absence"},"sub_type":{"type":["string","null"],"description":"`removal` when the request asks to take back days that were already approved,\notherwise null.\n","example":null},"status":{"type":"string","enum":["pending","approved","rejected","cancelled","pending_removal"],"description":"The stored status.","example":"pending"},"employee_id":{"type":"string","format":"uuid","description":"The employee the request is for, whose balance and calendar it moves.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee":{"type":["object","null"],"description":"The same employee, by name, when the relation was loaded. Present on the validator\nqueues, absent where the endpoint does not load it.\n","properties":{"employee_id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"name":{"type":["string","null"],"example":"Muller Anna"}}},"requested_by":{"type":["object","null"],"description":"Who raised the request, when that is somebody other than the employee it is for\n(raised on their behalf). Null for the ordinary case of raising your own, so a\nclient can show provenance only when there is any.\n","properties":{"employee_id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"name":{"type":["string","null"]}}},"company_id":{"type":["string","null"],"format":"uuid"},"start":{"type":["string","null"],"format":"date-time","example":"2026-03-04T00:00:00+00:00"},"end":{"type":["string","null"],"format":"date-time","example":"2026-03-06T00:00:00+00:00"},"dates":{"type":"array","description":"The days actually asked for, which is what to read rather than the range: a\nrequest can skip days.\n","items":{"type":"string","format":"date"},"example":["2026-03-04","2026-03-05"]},"requested_time":{"type":"object","description":"Seconds asked for per day, keyed by date.","additionalProperties":{"type":"integer"},"example":{"2026-03-04":28800,"2026-03-05":28800}},"requested_seconds":{"type":"integer","description":"The sum of `requested_time`, for convenience.","example":57600},"next_availability":{"type":"object","description":"When an employee is next at work **if the request carrying this object goes through**,\nnext to what the general next-availability answer says today. The validator's view of a\nrequest: no second call, and no cache between the queue and the date.\n\nIt is deliberately not the same question as `GET \/user\/{employee_id}\/next-availability`:\n\n- **Anchored at the request, not at today**, so it reports the day *this* booking frees\n  rather than the next free day counting from now.\n- **Counts what has been decided plus this one request.** The base is what has been\n  signed off (accepted, plus an accepted absence somebody has asked to cancel \u2014 still\n  time off until that cancellation is approved). Other queued requests are left out:\n  they may be refused, and a date that moves because of a request this validator has not\n  seen is not one they can act on. (`current` does count every pending row \u2014 that\n  difference is intentional.)\n- **A removal reads as a reduction**, so its answer moves *earlier*, often into the past\n  (`in_past`), which is the signal that the employee is already back.\n\nAbsence, illness, special leave and legal holiday only. Home office never carries it: a\nhome office day is governed by a weekly limit, not time off that moves an availability\ndate. Neither does a request that can no longer move a date \u2014 `rejected`, `canceled` and\n`removed`.\n\n**Where it appears:** the absence lists (`\/absences`, `\/user\/{employee_id}\/absences`), the\nabsence-request reads and writes (`\/absence-requests`, `\/user\/{employee_id}\/absence-requests`\nand its `POST`\/`PUT`), `POST \/user\/{employee_id}\/absence-removal-requests`, and both\nvalidator queues (`\/validator\/pending-requests` \u2014 on each `absence_requests[]` \/\n`absence_removals[]` entry \u2014 and v2 `pending-requests\/absences`). It is **not** on the\ncancel responses (`POST ...\/absence-requests\/{id}\/cancel`), which report the outcome of an\nemployee's own action rather than something a validator is weighing up.\n\nOn the resource-backed payloads the key is **omitted** when there is nothing to say; on\nthe v1 validator queue, whose entries are built by hand, it is always present and `null`\nin that case. Both mean the same thing.\n","required":["if_approved","current"],"properties":{"if_approved":{"type":"object","description":"Availability as it would stand with this request applied.","required":["absent_from","next_available_date","next_available_at","available_now","in_past","extends_current_absence","message"],"properties":{"absent_from":{"type":["string","null"],"format":"date","description":"First day, today or later, that this request itself takes off. Null when it takes\nnothing off in the future: a removal request, or days that have all been and gone.\n","example":"2026-08-13"},"next_available_date":{"type":["string","null"],"format":"date","description":"The day the employee is back at work under this scenario. Null only when no\nworking day was found within the search horizon \u2014 an employee with no work shift,\nor one whose contract has ended.\n","example":"2026-08-17"},"next_available_at":{"type":["string","null"],"description":"Exact moment they are back (`YYYY-MM-DD HH:MM:SS`) when a half day pins one down;\nnull when only the date is meaningful.\n","example":null},"available_now":{"type":"boolean","description":"Whether the employee is at work right now under this scenario. True together with\na future `absent_from` is the ordinary case for a request that starts later.\n","example":true},"in_past":{"type":"boolean","description":"True when `next_available_date` is already behind us, i.e. approving this would\nnot keep anybody away from now on. Render it as \"already available\" rather than as\na return date.\n","example":false},"extends_current_absence":{"type":"boolean","description":"True when this request starts on the very day the employee would otherwise have\ncome back, so it lengthens the absence already in place rather than opening a\nseparate one. False for a request with working days in between \u2014 show\n`absent_from` as well as the return date in that case, or the return date reads as\na contradiction of `available_now`.\n","example":false},"message":{"type":["string","null"],"description":"Ready-to-display line, already covering the three cases: `Available on\n2026-08-17`, `Off from 2026-08-13, available on 2026-08-17`, or `Already available\n(was back on 2026-08-03)`. Show it as returned.\n","example":"Off from 2026-08-13, available on 2026-08-17"}}},"current":{"type":"object","description":"Today's general answer, unchanged \u2014 the same figure\n`GET \/user\/{employee_id}\/next-availability` returns, so the two screens never disagree.\n","required":["next_available_date","message"],"properties":{"next_available_date":{"type":["string","null"],"format":"date","description":"Next day the employee is available, counting from now. Null when they are\navailable right now.\n","example":"2026-08-12"},"message":{"type":["string","null"],"description":"Ready-to-display line, or null while the employee is available.","example":"Back on 2026-08-12"}}}},"example":{"if_approved":{"absent_from":"2026-08-13","next_available_date":"2026-08-17","next_available_at":null,"available_now":true,"in_past":false,"extends_current_absence":false,"message":"Off from 2026-08-13, available on 2026-08-17"},"current":{"next_available_date":"2026-08-12","message":"Back on 2026-08-12"}}},"comment":{"type":["string","null"],"description":"The requester's note.","example":"Family trip"},"created":{"type":["string","null"],"format":"date-time"},"modified":{"type":["string","null"],"format":"date-time"},"validators":{"type":"array","description":"Everyone this request asks, with their answer so far and where they sit, when the\napprovals relation was loaded. Rows superseded by a restarted chain are left out:\nthey record what a previous round asked and are not people still to answer.\n","items":{"type":"object","properties":{"employee_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string","description":"The name frozen on the row when it was written, so a validator who has since\nbeen deleted still reads correctly.\n","example":"Lemaire Farid"},"status":{"type":"string","enum":["pending","accepted","rejected"]},"comment":{"type":["string","null"]},"step_position":{"type":["integer","null"],"description":"Their rung in the chain, or null for a watcher, who sits outside the ladder.\n","example":1},"watcher":{"type":"boolean"},"mandatory":{"type":"boolean","description":"Whether their approval is required for the step to complete, whatever its\nquorum.\n"}}}}}},{"type":"object","description":"Where a queued request sits in its approval chain, from the point of view of the\nvalidator who asked for the queue.\n\nA request routes through a chain of steps, and only the step currently holding it\nmay decide. A validator therefore sees requests in two states: theirs to act on\nnow, and theirs to expect. Both are listed, so a validator on a later step is not\nsurprised by a request appearing from nowhere once the step below clears.\n\nRequests raised before approval chains existed carry no step: `step` is null and\n`can_decide_now` is true, because there is no ladder to wait on.\n","required":["can_decide_now","watcher","step","awaiting"],"properties":{"can_decide_now":{"type":"boolean","description":"Whether this validator may record a decision on the request right now.\nFalse while the request is at a step below theirs: the decision endpoints\nanswer 409 in that case, and a client should not offer the action.\n","example":true},"watcher":{"type":"boolean","description":"Whether this validator holds the request as a watcher rather than as a step\nvalidator. Watchers sit outside the ladder: they carry no step and, when\ngranted the power, may settle the request at any point.\n","example":false},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","description":"The validators the request is waiting on right now: those still to answer at\nthe step holding it, the caller aside. Empty when the caller is the only one\nleft to answer.\n","items":{"type":"string"},"example":["Muller Jonas"]}}}]}},"pagination":{"type":"object","required":["page","total_pages","total","per_page"],"properties":{"page":{"type":"integer","example":1},"total_pages":{"type":"integer","example":2},"total":{"type":"integer","example":14},"per_page":{"type":"integer","example":10}}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440010","type":"home_office","sub_type":null,"status":"pending","employee_id":"550e8400-e29b-41d4-a716-446655440001","employee":{"employee_id":"550e8400-e29b-41d4-a716-446655440001","first_name":"Anna","last_name":"Muller","name":"Muller Anna"},"requested_by":null,"company_id":"550e8400-e29b-41d4-a716-446655440005","start":"2026-03-04T00:00:00+00:00","end":"2026-03-04T00:00:00+00:00","dates":["2026-03-04"],"requested_time":{"2026-03-04":28800},"requested_seconds":28800,"comment":null,"created":"2026-03-01T09:12:00+00:00","modified":"2026-03-01T09:12:00+00:00","validators":[{"employee_id":"550e8400-e29b-41d4-a716-446655440020","name":"Lemaire Farid","status":"pending","comment":null,"step_position":1,"watcher":false,"mandatory":false}],"can_decide_now":true,"watcher":false,"step":{"position":1,"total":2,"name":"Team lead","status":"active","required":1,"mandatory":false},"awaiting":[]}],"pagination":{"page":1,"total_pages":2,"total":14,"per_page":10}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The caller is outside this PBX, or asked for an employee record that is\nnot their own.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have access to this PBX."}}}}}},"404":{"description":"Not found. No such employee in this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User not found."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/v2\/{pbx}\/employee\/{employee}\/pending-requests\/time-point-corrections":{"get":{"tags":["TempusValidators"],"summary":"List the time point corrections waiting on you to decide (user)","operationId":"tempusV2ListPendingTimePointCorrections","security":[{"bearerAuth":[]}],"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api","description":"Tempus production API server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api","description":"Tempus staging API server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api","description":"Tempus dev API server"}],"description":"The time point correction requests this employee is asked to decide: changes to a\nrecorded clock event, raised by the employee whose sheet it is.\n\nRead off the approval rows addressed to them, so approval chains are honoured\nexactly as the decision endpoints honour them. A correction at a step below theirs is\nincluded with `can_decide_now: false`.\n\nYour own employee record only: another employee's id returns 403.\n\nThe payload is the v2 correction shape: people are identified by `employee_id`\nrather than v1's `requested_ext_id` (a telephony extension is not how a Tempus\nemployee is identified), and the timestamps are ISO 8601 rather than several\npre-formatted renderings of the same instant.\n\nOpen one with\n`GET \/tempus\/api\/v1\/{pbx_id}\/validator\/pending-corrections\/{correction_id}\/details`,\nwhich returns the day's other time points for context and is unchanged.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the PBX tenant. Must be the tenant the token belongs to; anything else is\nrefused with 403 rather than answered from another tenant.\n","example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the Tempus employee whose queue this is. Must be the caller's own employee\nrecord: a queue is built from the approval rows addressed to one person, so another\nemployee's id is refused rather than quietly answered with your own.\n","example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number to return.","example":1},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":10},"description":"Number of entries per page.","example":10},{"name":"filter[requester_id]","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Narrow the queue to one person who raised requests. Named `requester_id` rather than\n`employee_id` because the employee in the path is the validator: these routes have two\nemployees in play. A requester you hold no rows on yields an empty page rather than a\n403, since nothing was hidden from you.\n","example":"550e8400-e29b-41d4-a716-446655440002"}],"responses":{"200":{"description":"OK. Paginated corrections waiting on this employee.","content":{"application\/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"allOf":[{"type":"object","description":"A time point correction: a request to change a recorded clock event.\n\nv2 of the payload, on the same principles as the v2 transaction. `requested_ext_id`\nbecomes `employee_id` (a telephony extension is not how a Tempus employee is\nidentified, and resolving it cost two queries per row), and the timestamps are ISO 8601\nrather than several pre-formatted variants of the same instant: v1 returned `date`,\n`new_datetime`, `old_datetime`, `new_time` and `old_time`, which is one moment rendered\nfive ways and leaves a client unable to reformat it.\n\nA correction may have no \"old\" side, for instance when it asks to add a clock event\nthat was never recorded. Then `old_status`, `old_sub_status` and `old_time` are null.\n","required":["id","status","employee_id","old_status","new_status"],"properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440040"},"status":{"type":"string","enum":["pending","approved","rejected","cancelled"],"example":"pending"},"employee_id":{"type":"string","format":"uuid","description":"The employee whose attendance sheet this corrects.","example":"550e8400-e29b-41d4-a716-446655440001"},"employee":{"type":["object","null"],"description":"The same employee, by name, when the relation was loaded.","properties":{"employee_id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"name":{"type":["string","null"],"example":"Muller Anna"}}},"timepoint_id":{"type":["string","null"],"format":"uuid","description":"The clock event being changed, or null when the correction asks to add one that was\nnever recorded.\n"},"old_status":{"type":["object","null"],"description":"The status the clock event carries now.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Working"},"style":{"type":"object","description":"How a status is presented. Kept as one nested object rather than flattened into\n`font_color` \/ `background_color` \/ `icon` siblings, so a client can pass it around\nwithout unpacking it.\n","properties":{"font_color":{"type":["string","null"],"example":"#ffffff"},"background_color":{"type":["string","null"],"example":"#2f6f4f"},"icon":{"type":["string","null"],"example":"la la-clock"}}}}},"new_status":{"type":["object","null"],"description":"The status the correction asks for.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Break"},"style":{"type":"object","description":"How a status is presented. Kept as one nested object rather than flattened into\n`font_color` \/ `background_color` \/ `icon` siblings, so a client can pass it around\nwithout unpacking it.\n","properties":{"font_color":{"type":["string","null"],"example":"#ffffff"},"background_color":{"type":["string","null"],"example":"#2f6f4f"},"icon":{"type":["string","null"],"example":"la la-clock"}}}}},"old_sub_status":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"style":{"type":"object","description":"How a status is presented. Kept as one nested object rather than flattened into\n`font_color` \/ `background_color` \/ `icon` siblings, so a client can pass it around\nwithout unpacking it.\n","properties":{"font_color":{"type":["string","null"],"example":"#ffffff"},"background_color":{"type":["string","null"],"example":"#2f6f4f"},"icon":{"type":["string","null"],"example":"la la-clock"}}}}},"new_sub_status":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"style":{"type":"object","description":"How a status is presented. Kept as one nested object rather than flattened into\n`font_color` \/ `background_color` \/ `icon` siblings, so a client can pass it around\nwithout unpacking it.\n","properties":{"font_color":{"type":["string","null"],"example":"#ffffff"},"background_color":{"type":["string","null"],"example":"#2f6f4f"},"icon":{"type":["string","null"],"example":"la la-clock"}}}}},"old_location":{"type":["object","null"],"description":"The location the time point was pointed at when the correction was raised.\nNull when it had none.\n","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"geofence_radius_m":{"type":["integer","null"]}}},"new_location":{"type":["object","null"],"description":"The location the correction asks the time point to be recorded at. Null\nwhen the correction does not touch the location, which is NOT the same as\nasking for it to be cleared: acceptance leaves the current location as is.\n","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"geofence_radius_m":{"type":["integer","null"]}}},"old_time":{"type":["string","null"],"format":"date-time","description":"When the clock event is recorded now, null when there is no old side.","example":"2026-03-04T09:03:00+00:00"},"new_time":{"type":["string","null"],"format":"date-time","description":"When the correction asks it to be.","example":"2026-03-04T09:00:00+00:00"},"correction_comment":{"type":["string","null"],"description":"Why the requester says the change is needed.","example":"Badge reader was down"},"new_comment":{"type":["string","null"],"description":"The comment the corrected clock event should carry."},"created":{"type":["string","null"],"format":"date-time"}}},{"type":"object","description":"Where a queued request sits in its approval chain, from the point of view of the\nvalidator who asked for the queue.\n\nA request routes through a chain of steps, and only the step currently holding it\nmay decide. A validator therefore sees requests in two states: theirs to act on\nnow, and theirs to expect. Both are listed, so a validator on a later step is not\nsurprised by a request appearing from nowhere once the step below clears.\n\nRequests raised before approval chains existed carry no step: `step` is null and\n`can_decide_now` is true, because there is no ladder to wait on.\n","required":["can_decide_now","watcher","step","awaiting"],"properties":{"can_decide_now":{"type":"boolean","description":"Whether this validator may record a decision on the request right now.\nFalse while the request is at a step below theirs: the decision endpoints\nanswer 409 in that case, and a client should not offer the action.\n","example":true},"watcher":{"type":"boolean","description":"Whether this validator holds the request as a watcher rather than as a step\nvalidator. Watchers sit outside the ladder: they carry no step and, when\ngranted the power, may settle the request at any point.\n","example":false},"step":{"type":["object","null"],"description":"The step this validator occupies, or null for a watcher and for a request\nwith no chain. Positions are numbered from 1 in the order the steps are\nasked.\n","required":["position","total","name","status","required","mandatory"],"properties":{"position":{"type":"integer","description":"This step's place in the chain, counting from 1.","example":2},"total":{"type":"integer","description":"How many steps the request's chain holds in all.","example":3},"name":{"type":"string","description":"The step's name, or a generated \"Step n\" label when the chain left it\nunnamed. Frozen when the request was raised, so renaming a step later\ndoes not relabel requests already in flight.\n","example":"Team lead"},"status":{"type":"string","enum":["pending","active","completed","bypassed","rejected"],"description":"The step's state. `active` is the step holding the request; `pending` has\nnot been reached; `bypassed` was skipped because the request was settled\nabove it.\n","example":"active"},"required":{"type":"integer","description":"How many approvals this step needs before it completes.","example":2},"mandatory":{"type":"boolean","description":"Whether this validator must approve for the step to complete. A\nmust-approve validator holds the step even once its quorum is met.\n","example":false}}},"awaiting":{"type":"array","description":"The validators the request is waiting on right now: those still to answer at\nthe step holding it, the caller aside. Empty when the caller is the only one\nleft to answer.\n","items":{"type":"string"},"example":["Muller Jonas"]}}}]}},"pagination":{"type":"object","required":["page","total_pages","total","per_page"],"properties":{"page":{"type":"integer","example":1},"total_pages":{"type":"integer","example":4},"total":{"type":"integer","example":38},"per_page":{"type":"integer","example":10}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Forbidden. The caller is outside this PBX, or asked for an employee record that is\nnot their own.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You do not have access to this PBX."}}}}}},"404":{"description":"Not found. No such employee in this PBX.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"User not found."}}}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/next-availability":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"Get the next availability date for an employee (user)","operationId":"tempusGetUserNextAvailability","description":"Searches forward from a start moment for the next time the employee is available and returns it. The response is a flat object and is not wrapped in a `data` envelope. When the employee is already available at that moment, `next_available_date` is `null` and `available_now` is `true` : there is no *future* availability to report, so a date equal to the current\/`from` day is never returned for that case.\nThe search is **time-aware**: a half day off only blocks the part of the day it covers. A morning absence (e.g. 08:00\u201312:00) that is under way returns **today** together with `next_available_at` = the moment it ends; an afternoon one reads as available *before* it starts and returns the next working day (date only) from the moment it does. `message` is a ready-to-display line for either case.\nWhen no available date is found within the search window (and the employee is not available now), the endpoint responds with 404 and a flat body reporting the searched range. A 404 is also returned when the employee cannot be found for the tenant.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose next availability is requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"from","in":"query","required":false,"description":"Moment the availability search starts from. Defaults to **now** when omitted. A bare date evaluates from that day's 00:00; pass a date-time (`YYYY-MM-DD HH:MM:SS`) to ask \"is the employee available at this moment?\" \u2014 half days are honoured to the clock.\n","schema":{"type":"string"},"example":"2026-03-01 09:00:00"},{"name":"max_days","in":"query","required":false,"description":"Maximum number of days to search forward. Defaults to 90 when omitted.","schema":{"type":"integer","minimum":1,"maximum":365,"default":90},"example":90}],"responses":{"200":{"description":"The next available date for the employee. Flat object, not wrapped in data.","content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"next_available_date":{"type":"string","format":"date","nullable":true,"description":"Date the employee is next available, or `null` when they are available at the moment checked (see `available_now`). Equal to the current\/`from` day only when a half day off already under way ends later that same day.\n"},"next_available_at":{"type":"string","nullable":true,"description":"Exact moment the employee is back (`YYYY-MM-DD HH:MM:SS`) when the data pins one down \u2014 the end of a morning half day off already under way. `null` when availability is only known at day granularity (whole days off, and afternoon half days where the working day is over).\n"},"message":{"type":"string","nullable":true,"description":"Ready-to-display line: \"Back on <date>\", or \"Back on <date> at <time>\" when a half day off brings the employee back the same day. `null` while available.\n"},"available_now":{"type":"boolean","description":"True when the employee is available at the moment checked."},"current":{"type":"object","description":"State of the `from` day, so a client can explain the situation.","properties":{"date":{"type":"string","format":"date"},"available":{"type":"boolean"},"reason":{"type":"string","description":"`available`, `absence`, `public_holiday`, `special_holiday` or `non_working_day`."},"absence":{"type":"object","nullable":true,"description":"The absence covering the moment checked; `null` when none does.","properties":{"type":{"type":"string"},"sub_type":{"type":"string","nullable":true},"status":{"type":"string"},"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"}}},"absence_window":{"type":"object","nullable":true,"description":"The intraday window a half day off covers on this day \u2014 reported even when the employee is available (before it starts \/ after it ends). `null` when the day is off as a whole or not off at all.\n","properties":{"start":{"type":"string"},"end":{"type":"string"},"part":{"type":"string","enum":["am","pm"]}}}}},"employee_id":{"type":"string","format":"uuid"},"checked_from":{"type":"string","format":"date"},"checked_from_at":{"type":"string","description":"The exact moment the search evaluated from."},"checked_until":{"type":"string","format":"date"}}},"example":{"success":true,"next_available_date":"2026-03-02","next_available_at":"2026-03-02 12:00:00","message":"Back on 2026-03-02 at 12:00","available_now":false,"current":{"date":"2026-03-02","available":false,"reason":"absence","absence":{"type":"legal","sub_type":null,"status":"approved","start":"2026-03-02","end":"2026-03-02"},"absence_window":{"start":"2026-03-02 08:00:00","end":"2026-03-02 12:00:00","part":"am"}},"employee_id":"550e8400-e29b-41d4-a716-446655440001","checked_from":"2026-03-02","checked_from_at":"2026-03-02 09:00:00","checked_until":"2026-05-30"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"No available date was found within the search window, or the employee could not be found for the tenant. The body is a flat object reporting the searched range.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"employee_id":{"type":"string","format":"uuid"},"checked_from":{"type":"string","format":"date"},"checked_from_at":{"type":"string"},"checked_until":{"type":"string","format":"date"}}},"example":{"success":false,"message":"No available date found within the search range.","employee_id":"550e8400-e29b-41d4-a716-446655440001","checked_from":"2026-03-01","checked_from_at":"2026-03-01 00:00:00","checked_until":"2026-05-30"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/public-holidays":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"List public holidays for an employee (user)","operationId":"tempusListUserPublicHolidays","description":"Returns a paginated list of public holidays relevant to the employee. The countries are derived from the employee's contracts that overlap the requested date range, and holidays are returned for those countries. When no date filters are supplied the range defaults to the current calendar year. Filtering and sorting are powered by Spatie Query Builder.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose public holidays are requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":false,"description":"Return holidays on or after this date. Defaults to the start of the current year.","schema":{"type":"string","format":"date"},"example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Return holidays on or before this date. Defaults to the end of the current year.","schema":{"type":"string","format":"date"},"example":"2026-12-31"},{"name":"sort","in":"query","required":false,"description":"Sort field. Allowed: date. Prefix with - for descending.","schema":{"type":"string"},"example":"date"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":15},"example":15}],"responses":{"200":{"description":"Paginated list of public holidays for the employee's countries.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusPublicHoliday"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/profile":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"Get the Tempus profile for an employee (user)","operationId":"tempusGetUserProfile","description":"Returns the consolidated Tempus profile for a single employee, assembled from the employee's active contract and company: the company, the contract dates, basic employee contact fields, and per-feature summaries (absence, home office allowance, overtime). The caller may only view their own profile: the request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own, with 404 when the employee or its linked user account cannot be found, and with 422 when the employee has no active contract to build a profile from.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose profile is requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"The assembled Tempus profile for the employee.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusUserProfile"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"The employee has no active contract, so no profile can be produced.","content":{"application\/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"Employee has no active contract."}}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/travel-time":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"List an employee's travel time credits","operationId":"tempusListUserTravelTime","description":"Returns the travel time credits recorded for the employee in the given date range, newest first, plus the current allowance in `meta`. Defaults to the current month when `from` and `to` are omitted. The caller may only read their own credits: the request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own, and with 404 when the employee cannot be found. When travel time is not configured for the PBX the list is empty and `meta.enabled` reflects the employee's own flag.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose credits are requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"from","in":"query","required":false,"description":"Start of the range, `Y-m-d`. Defaults to the first day of the current month.","schema":{"type":"string","format":"date"},"example":"2026-05-01"},{"name":"to","in":"query","required":false,"description":"End of the range, `Y-m-d`. Must not be earlier than `from`. Defaults to today.","schema":{"type":"string","format":"date"},"example":"2026-05-31"}],"responses":{"200":{"description":"The employee's travel time credits and current allowance.","content":{"application\/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusTravelTimeCredit"}},"meta":{"type":"object","required":["enabled","minutes_per_request","max_per_day","used_today","remaining_today"],"properties":{"enabled":{"type":"boolean","description":"Whether travel time is enabled for this employee.","example":true},"minutes_per_request":{"type":"integer","format":"int32","description":"Payable minutes credited per request.","example":30},"max_per_day":{"type":"integer","format":"int32","description":"How many credits are allowed per date.","example":1},"used_today":{"type":"integer","format":"int32","description":"Credits already taken today.","example":1},"remaining_today":{"type":"integer","format":"int32","description":"Credits still available today.","example":0}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"The `from` or `to` query parameter is malformed, or `to` precedes `from`.","content":{"application\/json":{"schema":{"type":"object","required":["message","errors"],"properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"example":{"message":"The given data was invalid.","errors":{"to":["The to field must be a date after or equal to from."]}}}}}}}},"post":{"tags":["TempusProfile"],"summary":"Credit travel time to a day","operationId":"tempusStoreUserTravelTime","description":"Credits the employee's configured travel time allowance to a date and returns\nthe time point created.\n\nThe minutes are inserted immediately BEFORE the first status of that day,\nending exactly where that first status begins, so the working day grows and\nthe minutes count toward work time and overtime. When the day has no time\npoints at all, the credit is anchored at the PBX's configured empty day time\n(06:00 by default) and closed by the configured stop status. Repeat requests\non the same day chain backwards from the earlier credit, producing one\ncontiguous block.\n\nThe credit is recorded as an accepted time point correction, so it appears in\nthe employee's correction history and remains correctable afterwards. No\nacceptance email is sent.\n\nThe caller may only credit their own travel time: the request is rejected with\n403 when the authenticated user has no access to the tenant or the employee\nrecord is not their own, and with 404 when the employee cannot be found.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee to credit.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":false,"content":{"application\/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The date to credit, `Y-m-d`. Defaults to today. Must not be in the future, and must not be older than the PBX's configured `travel_time.max_past_days` window (31 days by default).\n","example":"2026-05-11"},"comment":{"type":["string","null"],"maxLength":500,"description":"Optional note stored on the credit. Defaults to a generated \"Travel time requested\" comment.\n","example":"Client site visit"}}}}}},"responses":{"201":{"description":"The travel time credit was applied.","content":{"application\/json":{"schema":{"type":"object","required":["message","data","meta"],"properties":{"message":{"type":"string","example":"Travel time has been added."},"data":{"type":"object","required":["timepoint_id","status_id","start_time"],"properties":{"timepoint_id":{"type":"string","format":"uuid","description":"UUID of the time point created for the credit.","example":"550e8400-e29b-41d4-a716-446655440012"},"status_id":{"type":"string","format":"uuid","description":"UUID of the PBX travel time status.","example":"550e8400-e29b-41d4-a716-446655440011"},"start_time":{"type":"string","description":"Start of the credited block, `Y-m-d H:i:s`.","example":"2026-05-11 07:30:00"},"end_time":{"type":["string","null"],"description":"End of the credited block, `Y-m-d H:i:s`.","example":"2026-05-11 08:00:00"},"minutes":{"type":["integer","null"],"format":"int32","description":"Minutes credited. Smaller than the configured allowance when the block had to be clamped to the start of the day.\n","example":30},"comment":{"type":["string","null"],"description":"The comment stored on the credit.","example":"Client site visit"}}},"meta":{"type":"object","required":["used_today","remaining_today"],"properties":{"used_today":{"type":"integer","format":"int32","example":1},"remaining_today":{"type":"integer","format":"int32","example":0}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Either the `date` or `comment` field failed validation (standard\nvalidation error body), or a travel time guard refused the request. Guard\nrefusals carry a stable machine readable `code` alongside the translated\n`message`:\n\n| code | meaning |\n|---|---|\n| `not_allowed` | Travel time is not enabled for this employee. |\n| `employee_user_missing` | The employee is not linked to a user account. |\n| `status_not_configured` | No status is marked as travel time for the PBX. |\n| `status_ambiguous` | More than one status is marked as travel time. |\n| `stop_status_not_configured` | The day is empty and no stop status is configured. |\n| `stop_status_same_as_travel` | The stop status is misconfigured to equal the travel status. |\n| `minutes_not_configured` | The configured duration is zero or negative. |\n| `date_in_future` | The requested date is in the future. |\n| `date_locked` | The requested date is older than the allowed window. |\n| `no_contract` | The employee has no active contract on that date. |\n| `absence_day` | The date is covered by an approved absence. |\n| `limit_reached` | The per-date allowance is already used up. |\n| `no_room_before_first_status` | The day's first status is at midnight, leaving no room. |\n","content":{"application\/json":{"schema":{"oneOf":[{"type":"object","title":"Guard refusal","required":["message","code"],"properties":{"message":{"type":"string","example":"The travel time limit for this date has already been reached."},"code":{"type":"string","example":"limit_reached"}}},{"type":"object","title":"Field validation error","required":["message","errors"],"properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}]}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/user-companies":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"List companies associated with an employee (user)","operationId":"tempusListUserCompanies","description":"Returns a paginated list of the employee's contracts, each enriched with its company details. When no active filter is supplied, the currently active contract is flagged as the main company. Filtering and sorting are powered by Spatie Query Builder. The caller may only list their own companies: the request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own, and with 404 when the employee cannot be found.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose companies are requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":false,"description":"Return contracts whose start date is on or after this date.","schema":{"type":"string","format":"date"},"example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Return contracts whose end date is on or before this date. Must be on or after filter[from].","schema":{"type":"string","format":"date"},"example":"2026-12-31"},{"name":"filter[active]","in":"query","required":false,"description":"Restrict to active (true\/1) or ended (false\/0) contracts.","schema":{"type":"string","enum":["true","false","1","0"]},"example":"true"},{"name":"sort","in":"query","required":false,"description":"Sort field. Allowed: from (contract_start), to (contract_end). Prefix with - for descending.","schema":{"type":"string"},"example":"-from"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100},"example":15}],"responses":{"200":{"description":"Paginated list of the employee's companies.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusUserCompany"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/holidays-reports":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusProfile"],"summary":"Get the holidays report for an employee (user)","operationId":"tempusGetUserHolidaysReport","description":"Returns the legal-holiday report for the employee for a given year, derived from the transaction ledger. The report includes the possible, taken, expired and remaining holiday balances, the compensatory balance and extra time, plus a per-year pool details list. The response is a flat object and is not wrapped in a `data` envelope. The request is rejected with 403 when the authenticated user does not belong to the requested tenant, and with 404 when the employee cannot be found.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose holidays report is requested.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"year","in":"query","required":false,"description":"Four-digit year for the report. Defaults to the current year when omitted.","schema":{"type":"string","pattern":"^\\d{4}$"},"example":"2026"}],"responses":{"200":{"description":"The holidays report for the employee. Flat object, not wrapped in data.","content":{"application\/json":{"schema":{"type":"object","properties":{"possible_holidays":{"type":"number","description":"Total holiday credit plus overtime balance available."},"taken_holidays":{"type":"number","description":"Holiday time already taken."},"expired_holidays":{"type":"number"},"remaining_holidays":{"type":"number","description":"Remaining legal-holiday balance."},"pools_times_details_for_year":{"type":"array","items":{"type":"object"}},"compensatory_balance":{"type":"number"},"extra_time":{"type":"number"}}},"example":{"possible_holidays":936000,"taken_holidays":288000,"expired_holidays":0,"remaining_holidays":648000,"pools_times_details_for_year":[],"compensatory_balance":0,"extra_time":0}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user does not belong to the requested tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/compiled-user-workshifts":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusWorkTimes"],"summary":"List compiled workshifts for an employee (user)","operationId":"tempusListCompiledUserWorkshifts","description":"Returns the paginated list of compiled (precomputed) workshift entries for a\nsingle Tempus employee within the given PBX tenant. Each entry summarizes the\nworked time the Tempus engine has rolled up for one calendar day, attributing\nit to the employee's effective work shift and work week.\n\nResults are sorted by `date` descending by default and support `from`\/`to`\ndate filtering. The authenticated user may only read their own compiled\nworkshifts; requesting another employee's data returns 403.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}},{"name":"employee_id","in":"path","required":true,"description":"UUID of the Tempus employee whose compiled workshifts are listed.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440001"}},{"name":"filter[from]","in":"query","required":false,"description":"Include only entries on or after this calendar date (YYYY-MM-DD).","schema":{"type":"string","format":"date","example":"2024-03-01"}},{"name":"filter[to]","in":"query","required":false,"description":"Include only entries on or before this calendar date (YYYY-MM-DD).","schema":{"type":"string","format":"date","example":"2024-03-31"}},{"name":"sort","in":"query","required":false,"description":"Sort field. Use `date` for ascending or `-date` for descending.","schema":{"type":"string","enum":["date","-date"],"example":"-date"}},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1,"example":1}},{"name":"per_page","in":"query","required":false,"description":"Number of records per page (1 to 100).","schema":{"type":"integer","minimum":1,"maximum":100,"example":15}}],"responses":{"200":{"description":"Paginated collection of compiled workshift entries.","content":{"application\/json":{"schema":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusCompiledUserWorkshift"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user may only view their own compiled workshifts.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You can only view your own compiled user workshifts."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/interactive-calendar":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusWorkTimes"],"summary":"Build the interactive calendar for an employee (user)","operationId":"tempusBuildInteractiveCalendar","description":"Builds the interactive home-office and absence calendar for a single Tempus\nemployee (`ext_id`) over a from\/to month-year window within the given PBX\ntenant. The window must be valid (the `to` period must be greater than or\nequal to `from`) and may not exceed 24 months.\n\nThe authenticated user must belong to the same PBX tenant. Viewing another\nemployee's calendar requires absence-validation or home-office-validation\nscope over that employee; otherwise a 403 is returned. The response is a\nJSON object whose `data` payload is assembled by the calendar builder and\nvaries with the requested window.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["ext_id","from","to"],"properties":{"ext_id":{"type":"string","format":"uuid","description":"UUID of the target Tempus employee whose calendar is built.","example":"550e8400-e29b-41d4-a716-446655440001"},"from":{"type":"object","description":"Start of the month-year window (inclusive).","required":["year","month"],"properties":{"year":{"type":"integer","minimum":1970,"maximum":2100,"example":2024},"month":{"type":"integer","minimum":1,"maximum":12,"example":3}}},"to":{"type":"object","description":"End of the month-year window (inclusive).","required":["year","month"],"properties":{"year":{"type":"integer","minimum":1970,"maximum":2100,"example":2024},"month":{"type":"integer","minimum":1,"maximum":12,"example":6}}}}},"example":{"ext_id":"550e8400-e29b-41d4-a716-446655440001","from":{"year":2024,"month":3},"to":{"year":2024,"month":6}}}}},"responses":{"200":{"description":"The assembled interactive calendar for the requested window.","content":{"application\/json":{"schema":{"type":"object","description":"Interactive calendar payload assembled by the calendar builder. Not wrapped in an envelope; the `data` key below is a field of the payload, not a resource wrapper. The concrete contents depend on the requested window and the employee's schedule, absences and home office entries.\n","properties":{"ext_id":{"type":"string","format":"uuid","description":"The target employee id."},"month_calendars":{"type":"object","description":"Object keyed by `YYYY-MM`; each value is one month grid (days plus week rows).","additionalProperties":{"type":"object"}},"data":{"type":"object","description":"Aggregated calendar data: `public_holidays`, `home_office_module`, `absence_module`, `compiled_workshifts` (seconds of required work per day) and `active_company_id` (nullable).\n"}}},"example":{"ext_id":"550e8400-e29b-41d4-a716-446655440002","month_calendars":{"2026-07":{"key":"2026-07","year":2026,"month_index":7,"month_name":"July","formatted_date":"2026-06-29 - 2026-08-02","data":{"2026-07-14":{"day":14,"day_of_week":2,"is_same_month":true,"entry":{"type":"public-holiday","id":"550e8400-e29b-41d4-a716-446655440000","date":"2026-07-14"},"entries":[{"type":"public-holiday","id":"550e8400-e29b-41d4-a716-446655440000","date":"2026-07-14"}]}},"weeks":[{"week_of_year":28,"dates":["2026-07-06","2026-07-07","2026-07-08","2026-07-09","2026-07-10","2026-07-11","2026-07-12"]}]}},"data":{"public_holidays":{"550e8400-e29b-41d4-a716-446655440000":{"id":"550e8400-e29b-41d4-a716-446655440000","date":"2026-07-14","name":"National Day"}},"home_office_module":{"module_enabled":true,"has_permission_to_validate":true,"has_permission_to_request":true,"calendar":{"approved_days":["2026-07-20"],"requested_days":["2026-07-27"],"removed_days":[],"comment":""},"summary":{"2026":{"used":5,"allowance":40,"remaining":35}},"validated_dates":[]},"absence_module":{"module_enabled":true,"has_permission_to_validate":true,"has_permission_to_request":true,"absences":[],"absence_requests":[],"absence_removals":[],"summary":{"2026":{"possible":"25 days","taken":"5 days","remaining":"20 days"}}},"compiled_workshifts":{"2026-07-01":28800,"2026-07-14":0},"active_company_id":"550e8400-e29b-41d4-a716-446655440030"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the tenant, or lacks validation scope\nover the requested employee's calendar.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You are not authorized to view this calendar."}}}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/user-overtime-decision\/getOvertime":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusOvertime"],"summary":"Calculate overtime for an employee over a date range (user)","operationId":"tempusGetUserOvertime","description":"Calculates the accumulated overtime for a single Tempus employee within a date range and returns it split into `business` (overtime worked on regular business days) and `non_working` (overtime worked on weekends, public holidays and other non-working days). Both figures are expressed in seconds.\n\nThe window is taken from the `start` and `end` query parameters. When neither is supplied the endpoint falls back to the employee's current overtime period. The range may not exceed the configured maximum number of months (default 3); a longer range is rejected with 422. The employee must belong to the requested PBX tenant, otherwise the request returns 404.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the Tempus employee.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"start","in":"query","required":false,"description":"Start of the range (any parseable date). Must be on or before `end`. When omitted the employee's current overtime period start is used.\n","schema":{"type":"string","format":"date"},"example":"2024-03-01"},{"name":"end","in":"query","required":false,"description":"End of the range (any parseable date). Must be on or after `start` and within the configured maximum span from `start`. When omitted the employee's current overtime period end is used.\n","schema":{"type":"string","format":"date"},"example":"2024-03-31"}],"responses":{"200":{"description":"Calculated overtime totals in seconds.","content":{"application\/json":{"schema":{"type":"object","required":["business","non_working"],"properties":{"business":{"type":"integer","description":"Overtime accumulated on regular business days, in seconds.","example":7200},"non_working":{"type":"integer","description":"Overtime accumulated on non-working days (weekends, public holidays), in seconds.\n","example":1800}}},"example":{"business":7200,"non_working":1800}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/user-overtime-decision":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusOvertime"],"summary":"List a specific employee's overtime decisions (user)","operationId":"tempusListUserOvertimeDecisions","description":"Returns a paginated list of overtime decisions recorded for a single Tempus employee within the PBX tenant. Each item is serialized by the `UserOvertimeDecisionResource`. When no `filter[overtime_calculation_period_id]` is supplied the list is automatically restricted to the employee's current overtime period. The caller must be authorized to view the employee's own decisions, otherwise the request is rejected with 403, and the employee must belong to the requested PBX tenant, otherwise 404 is returned.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the Tempus employee.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[overtime_calculation_period_id]","in":"query","required":false,"description":"Restrict results to a single overtime calculation period. When omitted the current period is used automatically.\n","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440060"},{"name":"sort","in":"query","required":false,"description":"Sort order. Supports `created_at` and `overtime_calculation_period.start`, each prefixable with `-` for descending. Defaults to `-created_at`.\n","schema":{"type":"string"},"example":"-created_at"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":2000,"default":20},"example":20}],"responses":{"200":{"description":"Paginated list of the employee's overtime decisions.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusUserOvertimeDecision"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller is not authorized to view this employee's overtime decisions."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusOvertime"],"summary":"Create or update an employee's overtime decision (user)","operationId":"tempusStoreUserOvertimeDecision","description":"Creates or updates the overtime decision for a single Tempus employee for an overtime calculation period. The endpoint recalculates the period's overtime, derives `to_pay` \/ `to_increment` from the chosen `decision` (or from an explicit `to_pay`), and persists the decision via an upsert keyed on tenant, employee and period.\n\nThe stored row is fully derived server-side, so the response is the authoritative \"after\" state:\n\n* `decision_balance` \u2014 the balance carried into the period, taken from the\n  last LOCKED period's closing balance (never from an unlocked draft).\n* `decision_overtime` \u2014 the period's accrual UP TO TODAY. Days that have not\n  happened yet are not counted, so a decision taken mid-period no longer\n  reports the remaining workdays as undertime.\n* `to_pay` \u2014 what is cashed out, capped at\n  `decision_balance + decision_overtime` and never negative.\n* `to_increment` \u2014 `decision_overtime - to_pay`, i.e. what lands on the\n  balance. Negative when the payout is drawn from the carried-in balance.\n* `decision_new_balance` \u2014 what is left afterwards.\n\nWhen `overtime_calculation_period_id` is omitted the active period is resolved from the employee's current contract; if no active contract or no active decision period can be resolved the request is rejected with 422. If a decision for the period has already been processed (locked) it can no longer be changed and the request returns 403. The employee must belong to the requested PBX tenant, otherwise 404 is returned.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the Tempus employee.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["decision"],"properties":{"decision":{"type":"string","enum":["pay","add_to_balance","custom"],"description":"What to do with the calculated overtime. `pay` cashes out the whole accrual, `add_to_balance` rolls all of it into the employee's overtime balance, and `custom` means the split is given explicitly through `to_pay`.\n","example":"add_to_balance"},"to_pay":{"type":["integer","string"],"minimum":0,"description":"How much to cash out, as a whole number of seconds (`43200`) or as `\"HH:MM\"` (`\"12:00\"`). Overrides `decision`, so an employee can be paid part of the period and bank the rest; the remainder (`decision_overtime - to_pay`) goes to the balance. An explicit `0` means \"pay nothing\". Rejected with 422 when it exceeds the balance carried in plus the period's accrual. When omitted, the amount follows the `decision` label.\n","example":43200},"overtime_calculation_period_id":{"type":"string","format":"uuid","description":"Optional overtime calculation period the decision applies to. Must exist within the requested PBX tenant. When omitted the active period is resolved from the employee's current contract.\n","example":"550e8400-e29b-41d4-a716-446655440060"}}},"example":{"decision":"custom","overtime_calculation_period_id":"550e8400-e29b-41d4-a716-446655440060","to_pay":43200}}}},"responses":{"200":{"description":"The created or updated overtime decision.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusUserOvertimeDecision"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The overtime decision for this period has already been processed and is locked."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Validation failed: an unknown period, a `to_pay` larger than the employee's available time, or no active contract \/ decision period to resolve.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"You asked to be paid 12:00 but only 07:44 is available (balance carried in plus the overtime accrued this period)."},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"example":{"message":"You asked to be paid 12:00 but only 07:44 is available (balance carried in plus the overtime accrued this period).","errors":{"to_pay":["You asked to be paid 12:00 but only 07:44 is available (balance carried in plus the overtime accrued this period)."]}}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/user-overtime-decision-preference":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusOvertime"],"summary":"Read the employee's overtime decision preference (user)","operationId":"tempusShowUserOvertimeDecisionPreference","description":"Returns the employee's standing overtime decision preference, the same row HR edits under \"Decision Preferences\" on the employee record, plus the options, bounds and defaults needed to render the form.\n\n`data` is null when the employee has never saved a preference; in that case `meta.configured` is false and the company level rule applies. Read the starting values for the form from `meta.defaults`.\n\nSelf service only. The request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own, and with 404 when the employee cannot be found.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee. Must be the authenticated user's own employee record.","schema":{"type":"string","format":"uuid"},"example":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed"}],"responses":{"200":{"description":"The current preference, or null when none has been saved.","content":{"application\/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"oneOf":[{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreference"},{"type":"null"}]},"meta":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreferenceMeta"}}},"examples":{"configured":{"summary":"A preference has been saved","value":{"data":{"id":"9b1f0c62-4d0a-4e2f-9f43-6f4a5c8d1e70","scope":"employee","employee_id":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed","auto_decision_policy":"force_auto_decision","auto_decision_policy_label":"Force auto-decision (override manual)","policy_reason":"Prefers time off over payout","preferred_decision":"increment_up_to","preferred_decision_label":"Increment balance up to X hours","max_seconds":28800,"max_hours":8,"rest_policy":"add_to_balance","rest_policy_label":"Add to balance","is_active":true,"created_at":"2026-08-06 09:14:22","updated_at":"2026-08-06 10:02:51"},"meta":{"configured":true,"options":{"auto_decision_policy":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"},"preferred_decision":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"},"rest_policy":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}},"limits":{"min_seconds":3600,"max_seconds":115200,"min_hours":1,"max_hours":32},"defaults":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"pay_up_to","rest_policy":"add_to_balance","max_seconds":3600,"max_hours":1,"is_active":true}}}},"notConfigured":{"summary":"No preference saved yet","value":{"data":null,"meta":{"configured":false,"options":{"auto_decision_policy":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"},"preferred_decision":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"},"rest_policy":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}},"limits":{"min_seconds":3600,"max_seconds":115200,"min_hours":1,"max_hours":32},"defaults":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"pay_up_to","rest_policy":"add_to_balance","max_seconds":3600,"max_hours":1,"is_active":true}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["TempusOvertime"],"summary":"Save the employee's overtime decision preference (user)","operationId":"tempusUpdateUserOvertimeDecisionPreference","description":"Creates or replaces the employee's overtime decision preference. There is at\nmost one employee level row, so this is an upsert: 201 the first time, 200\non every later call. It writes the same row HR edits under \"Decision\nPreferences\", so a change made here is visible to HR immediately.\n\nThis is a full replace, not a patch. Fields left out are reset: `policy_reason`\nbecomes null and `is_active` becomes true.\n\n**Which fields are required depends on `auto_decision_policy`:**\n\n| `auto_decision_policy` | `preferred_decision` | cap | `rest_policy` |\n|---|---|---|---|\n| `skip_if_manual_decision` | required | required | required |\n| `force_auto_decision` | required | required | required |\n| `force_zero_overtime` | ignored, stored as null | ignored, stored as null | ignored, stored as null |\n\nThe cap may be sent as `max_seconds` or as `max_hours`; `max_seconds` wins\nwhen both are present. `max_hours` is multiplied by 3600 and rounded to the\nnearest second. One of the two is required unless the policy is\n`force_zero_overtime`.\n\nSelf service only. The request is rejected with 403 when the authenticated\nuser has no access to the tenant or the employee record is not their own,\nand with 404 when the employee cannot be found.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee. Must be the authenticated user's own employee record.","schema":{"type":"string","format":"uuid"},"example":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["auto_decision_policy"],"properties":{"auto_decision_policy":{"type":"string","enum":["skip_if_manual_decision","force_auto_decision","force_zero_overtime"],"description":"How the automatic overtime decision behaves.","example":"force_auto_decision"},"policy_reason":{"type":["string","null"],"maxLength":1000,"description":"Optional free text note. Reset to null when omitted.","example":"Prefers time off over payout"},"preferred_decision":{"type":["string","null"],"enum":["pay_up_to","increment_up_to",null],"description":"What to do with the overtime up to the cap. Required unless `auto_decision_policy` is `force_zero_overtime`, in which case it is ignored and stored as null.\n","example":"increment_up_to"},"max_hours":{"type":["number","null"],"format":"float","minimum":1,"maximum":32,"description":"The cap in hours. Converted to seconds on save. Send this or `max_seconds`, not necessarily both.\n","example":8},"max_seconds":{"type":["integer","null"],"format":"int32","minimum":3600,"maximum":115200,"description":"The cap in seconds. Takes precedence over `max_hours` when both are sent.","example":28800},"rest_policy":{"type":["string","null"],"enum":["add_to_balance","drop",null],"description":"What happens to the overtime above the cap. Required unless `auto_decision_policy` is `force_zero_overtime`, in which case it is ignored and stored as null.\n","example":"add_to_balance"},"is_active":{"type":"boolean","default":true,"description":"Whether the preference is applied. Defaults to true when omitted.","example":true}}},"examples":{"payUpTo":{"summary":"Pay overtime up to 8 hours, bank the rest","value":{"auto_decision_policy":"force_auto_decision","policy_reason":"Happy to be paid out for the first 8 hours","preferred_decision":"pay_up_to","max_hours":8,"rest_policy":"add_to_balance","is_active":true}},"incrementUpToSeconds":{"summary":"Bank overtime up to 10 hours using seconds, drop the rest","value":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"increment_up_to","max_seconds":36000,"rest_policy":"drop"}},"forceZeroOvertime":{"summary":"Not eligible for overtime, other fields omitted","value":{"auto_decision_policy":"force_zero_overtime","policy_reason":"Management contract, overtime not applicable"}},"deactivate":{"summary":"Keep the rule on record but stop applying it","value":{"auto_decision_policy":"force_auto_decision","preferred_decision":"pay_up_to","max_hours":8,"rest_policy":"add_to_balance","is_active":false}}}}}},"responses":{"200":{"description":"An existing preference was replaced.","content":{"application\/json":{"schema":{"type":"object","required":["message","data","meta"],"properties":{"message":{"type":"string","example":"Your overtime decision preference has been saved."},"data":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreference"},"meta":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreferenceMeta"}}},"example":{"message":"Your overtime decision preference has been saved.","data":{"id":"9b1f0c62-4d0a-4e2f-9f43-6f4a5c8d1e70","scope":"employee","employee_id":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed","auto_decision_policy":"force_auto_decision","auto_decision_policy_label":"Force auto-decision (override manual)","policy_reason":"Happy to be paid out for the first 8 hours","preferred_decision":"pay_up_to","preferred_decision_label":"Pay up to X hours","max_seconds":28800,"max_hours":8,"rest_policy":"add_to_balance","rest_policy_label":"Add to balance","is_active":true,"created_at":"2026-08-06 09:14:22","updated_at":"2026-08-06 10:02:51"},"meta":{"configured":true,"options":{"auto_decision_policy":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"},"preferred_decision":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"},"rest_policy":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}},"limits":{"min_seconds":3600,"max_seconds":115200,"min_hours":1,"max_hours":32},"defaults":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"pay_up_to","rest_policy":"add_to_balance","max_seconds":3600,"max_hours":1,"is_active":true}}}}}},"201":{"description":"The employee had no preference before and one was created.","content":{"application\/json":{"schema":{"type":"object","required":["message","data","meta"],"properties":{"message":{"type":"string","example":"Your overtime decision preference has been saved."},"data":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreference"},"meta":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreferenceMeta"}}},"example":{"message":"Your overtime decision preference has been saved.","data":{"id":"9b1f0c62-4d0a-4e2f-9f43-6f4a5c8d1e70","scope":"employee","employee_id":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed","auto_decision_policy":"force_zero_overtime","auto_decision_policy_label":"Force zero overtime (not eligible)","policy_reason":"Management contract, overtime not applicable","preferred_decision":null,"preferred_decision_label":null,"max_seconds":null,"max_hours":null,"rest_policy":null,"rest_policy_label":null,"is_active":true,"created_at":"2026-08-06 10:02:51","updated_at":"2026-08-06 10:02:51"},"meta":{"configured":true,"options":{"auto_decision_policy":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"},"preferred_decision":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"},"rest_policy":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}},"limits":{"min_seconds":3600,"max_seconds":115200,"min_hours":1,"max_hours":32},"defaults":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"pay_up_to","rest_policy":"add_to_balance","max_seconds":3600,"max_hours":1,"is_active":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"The body failed validation.","content":{"application\/json":{"schema":{"type":"object","required":["message","errors"],"properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"examples":{"missingCap":{"summary":"Neither max_hours nor max_seconds was sent","value":{"message":"The given data was invalid.","errors":{"max_hours":["A maximum number of hours is required for the selected preferred decision."]}}},"missingPreferredDecision":{"summary":"preferred_decision and rest_policy omitted on a policy that needs them","value":{"message":"The given data was invalid.","errors":{"preferred_decision":["The preferred decision field is required unless auto decision policy is in force_zero_overtime."],"rest_policy":["The rest policy field is required unless auto decision policy is in force_zero_overtime."]}}},"outOfRange":{"summary":"The cap is outside the accepted 1 to 32 hour range","value":{"message":"The given data was invalid.","errors":{"max_seconds":["The max seconds field must not be greater than 115200."]}}},"badEnum":{"summary":"An unknown enum value was sent","value":{"message":"The given data was invalid.","errors":{"auto_decision_policy":["The selected auto decision policy is invalid."]}}}}}}}}},"delete":{"tags":["TempusOvertime"],"summary":"Remove the employee's overtime decision preference (user)","operationId":"tempusDeleteUserOvertimeDecisionPreference","description":"Removes the employee level preference so the company level rule applies again. The row is soft deleted, so a later save creates a fresh one.\n\nReturns 404 when the employee has no preference to remove.\n\nSelf service only. The request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee. Must be the authenticated user's own employee record.","schema":{"type":"string","format":"uuid"},"example":"a24c68c0-92c0-4ca0-b749-84c6ddd671ed"}],"responses":{"200":{"description":"The preference was removed.","content":{"application\/json":{"schema":{"type":"object","required":["message","data","meta"],"properties":{"message":{"type":"string","example":"Your overtime decision preference has been removed."},"data":{"type":"null"},"meta":{"$ref":"#\/components\/schemas\/TempusOvertimeDecisionPreferenceMeta"}}},"example":{"message":"Your overtime decision preference has been removed.","data":null,"meta":{"configured":false,"options":{"auto_decision_policy":{"skip_if_manual_decision":"Skip if manual decision exists","force_auto_decision":"Force auto-decision (override manual)","force_zero_overtime":"Force zero overtime (not eligible)"},"preferred_decision":{"pay_up_to":"Pay up to X hours (specify max time)","increment_up_to":"Increment balance up to X hours (specify max time)"},"rest_policy":{"add_to_balance":"Add to balance","drop":"Drop (ignore remaining hours)"}},"limits":{"min_seconds":3600,"max_seconds":115200,"min_hours":1,"max_hours":32},"defaults":{"auto_decision_policy":"skip_if_manual_decision","preferred_decision":"pay_up_to","rest_policy":"add_to_balance","max_seconds":3600,"max_hours":1,"is_active":true}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.\n"},"404":{"description":"The employee was not found, or has no overtime decision preference to remove.","content":{"application\/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"No overtime decision preference has been set for this employee."}}}}}}}}},"\/{pbx_id}\/users-overtime-decisions":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusOvertime"],"summary":"List overtime decisions for all employees (user)","operationId":"tempusListUsersOvertimeDecisions","description":"Returns a paginated list of overtime decisions across all Tempus employees in the PBX tenant (the administrative view). Each item is serialized by the `UserOvertimeDecisionResource`. The caller must be authorized to view all overtime decisions for the tenant, otherwise the request is rejected with 403. Results may be filtered by overtime calculation period, decision type, lock state and company, and are sorted by `-created_at` by default.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[overtime_calculation_period_id]","in":"query","required":false,"description":"Restrict results to a single overtime calculation period.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440060"},{"name":"filter[decision_type]","in":"query","required":false,"description":"Restrict results to one or more decision types. Accepts a single value or a comma-separated list (for example `manual,automatic`).\n","schema":{"type":"string"},"example":"manual"},{"name":"filter[lock_states]","in":"query","required":false,"description":"Restrict results by lock state. `locked` returns processed (locked) decisions, `unlocked` returns decisions that have not been processed.\n","schema":{"type":"string","enum":["locked","unlocked"]},"example":"unlocked"},{"name":"filter[company_id]","in":"query","required":false,"description":"Restrict results to a single Tempus company.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20}],"responses":{"200":{"description":"Paginated list of overtime decisions for all employees.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusUserOvertimeDecision"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller is not authorized to view overtime decisions for this tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/overtime-calculation-periods":{"get":{"tags":["TempusOvertime"],"summary":"List overtime calculation periods for a tenant (user)","operationId":"tempusListOvertimeCalculationPeriods","description":"Returns a paginated list of overtime calculation periods belonging to the PBX tenant, ordered by start date descending. Each item is serialized by the `OvertimeCalculationPeriodResource`. The caller must be authorized to view overtime periods for the tenant, otherwise the request is rejected with 403. Results may be filtered by company, by start\/end date bounds and by lock state.\n\nThis endpoint is served under the standard `\/api\/v1` host (not the Tempus host).\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[company_id]","in":"query","required":false,"description":"Restrict results to a single Tempus company.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"filter[from]","in":"query","required":false,"description":"Only include periods whose start date is on or after this date.","schema":{"type":"string","format":"date"},"example":"2024-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Only include periods whose end date is on or before this date.","schema":{"type":"string","format":"date"},"example":"2024-12-31"},{"name":"filter[locked]","in":"query","required":false,"description":"Filter by lock state. A truthy value returns only locked periods; a falsy value returns all periods that are not locked.\n","schema":{"type":"string","enum":["true","false","1","0"]},"example":"false"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":15},"example":15}],"responses":{"200":{"description":"Paginated list of overtime calculation periods.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusOvertimeCalculationPeriod"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller is not authorized to view overtime periods for this tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/work-times":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusWorkTimes"],"summary":"List weekly work times for employees in the tenant (user)","operationId":"tempusListWorkTimes","description":"Returns a paginated map of weekly work-time aggregates for active employees in the PBX tenant. The response uses a hand-rolled Laravel paginator envelope (`data`, `links`, `meta`). The `data` object is keyed by employee UUID; each value is a map keyed by ISO week-start date (`YYYY-MM-DD`) plus a reserved `summary` key holding the totals across the queried range. Time values are formatted strings (`HH:MM:SS`) or `-` when no work shift was compiled for that week, and every one is mirrored by a signed `<field>Seconds` integer. Overtime figures are **balances**: a week below the required time is negative, so the weekly rows always sum to `summary`. Days after today are excluded from the aggregates (they would otherwise book a full requirement against zero worked time), so a still-running overtime period reports the same balance as `GET \/{pbx_id}\/user\/{employee_id}\/overtime`. When the authenticated user cannot view other employees (no validator scope) and no `filter[employee_id]` or `user_ids` is supplied, the result is scoped to the caller's own employee record; requesting another employee returns 403. The queried date range defaults to the current month and cannot exceed 100 days.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[from]","in":"query","required":false,"description":"Start date of the range (format `Y-m-d`). Defaults to the first day of the current month.","schema":{"type":"string","format":"date"},"example":"2024-03-01"},{"name":"filter[to]","in":"query","required":false,"description":"End date of the range (format `Y-m-d`). Defaults to today. The range may not exceed 100 days.","schema":{"type":"string","format":"date"},"example":"2024-03-31"},{"name":"filter[employee_id]","in":"query","required":false,"description":"One or more employee UUIDs to restrict the result to. Accepts a comma-separated string or an array.","schema":{"type":"array","items":{"type":"string","format":"uuid"}},"example":["550e8400-e29b-41d4-a716-446655440001"]},{"name":"user_ids","in":"query","required":false,"description":"Array of employee UUIDs to restrict the result to.","schema":{"type":"array","items":{"type":"string","format":"uuid"}},"example":["550e8400-e29b-41d4-a716-446655440001"]},{"name":"page","in":"query","required":false,"description":"Page number.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of employees per page (1 to 100, default 20).","schema":{"type":"integer","minimum":1,"maximum":100},"example":20}],"responses":{"200":{"description":"OK. Paginated envelope. The `data` object is keyed by employee UUID; each value is a weekly map keyed by week-start date plus a `summary` key.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Map keyed by employee UUID. Each value is a weekly work-time map.","additionalProperties":{"type":"object","description":"Map keyed by week-start date (`YYYY-MM-DD`) plus a reserved `summary` key. Each value is a weekly work-time aggregate.\n","additionalProperties":{"type":"object","description":"Aggregated work-time figures for a single week or the range summary.","properties":{"totalWorkedTime":{"type":"string","description":"Total worked time, formatted as `HH:MM:SS` (hours may exceed two digits).","example":"40:00:00"},"totalWorkedTimeSeconds":{"type":"integer","description":"Same figure in seconds.","example":144000},"requiredWorkedTime":{"type":"string","description":"Minimum required worked time as `HH:MM:SS`, or `-` when no work shift was compiled.","example":"40:00:00"},"requiredWorkedTimeSeconds":{"type":"integer","description":"Same figure in seconds; `0` when `requiredWorkedTime` is `-`.","example":144000},"businessDaysWorkedTime":{"type":"string","description":"Overtime balance on business days as `HH:MM:SS`, or `-` when no work shift was compiled. **Signed**: a week below the required time is negative (`-02:08:49`), so the weekly rows sum to the range total.\n","example":"-02:08:49"},"businessDaysWorkedTimeSeconds":{"type":"integer","description":"Same balance in seconds, negative for undertime; `0` when `businessDaysWorkedTime` is `-`. Sum this field rather than parsing the string.\n","example":-7729},"nonWorkingDaysWorkedTime":{"type":"string","description":"Overtime balance on non-working days as `HH:MM:SS` (signed), or `-` when no work shift was compiled.","example":"00:00:00"},"nonWorkingDaysWorkedTimeSeconds":{"type":"integer","description":"Same balance in seconds; `0` when `nonWorkingDaysWorkedTime` is `-`.","example":0},"hasOvertime":{"type":"boolean","description":"Whether the week recorded any overtime.","example":false}}}}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}},"example":{"data":{"550e8400-e29b-41d4-a716-446655440001":{"2024-03-04":{"totalWorkedTime":"41:31:51","totalWorkedTimeSeconds":149511,"requiredWorkedTime":"40:00:00","requiredWorkedTimeSeconds":144000,"businessDaysWorkedTime":"01:31:51","businessDaysWorkedTimeSeconds":5511,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":true},"2024-03-11":{"totalWorkedTime":"37:51:11","totalWorkedTimeSeconds":136271,"requiredWorkedTime":"40:00:00","requiredWorkedTimeSeconds":144000,"businessDaysWorkedTime":"-02:08:49","businessDaysWorkedTimeSeconds":-7729,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":false},"summary":{"totalWorkedTime":"79:23:02","totalWorkedTimeSeconds":285782,"requiredWorkedTime":"80:00:00","requiredWorkedTimeSeconds":288000,"businessDaysWorkedTime":"-00:36:58","businessDaysWorkedTimeSeconds":-2218,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":false}}},"links":{"first":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/550e8400-e29b-41d4-a716-446655440000\/work-times?page=1","last":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/550e8400-e29b-41d4-a716-446655440000\/work-times?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"path":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1\/550e8400-e29b-41d4-a716-446655440000\/work-times","per_page":20,"to":1,"total":1}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record, belongs to a different PBX, or requested work times for an employee they are not allowed to view.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/work-times":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusWorkTimes"],"summary":"List weekly work times for a single employee (user)","operationId":"tempusListUserWorkTimes","description":"Returns the weekly work-time aggregates for one employee. The response is a flat object (NOT wrapped in `data`) keyed by ISO week-start date (`YYYY-MM-DD`) plus a reserved `summary` key holding the totals across the queried range. Time values are formatted strings (`HH:MM:SS`) or `-` when no work shift was compiled for that week, and every one is mirrored by a signed `<field>Seconds` integer. Overtime figures are **balances**: a week below the required time is negative, so the weekly rows always sum to `summary`. Days after today are excluded from the aggregates (they would otherwise book a full requirement against zero worked time), so a still-running overtime period reports the same balance as `GET \/{pbx_id}\/user\/{employee_id}\/overtime`. Each entry also includes a `minWorkTimeReached` boolean. The caller may only request their own employee record; requesting another employee returns 403. The queried date range defaults to the current month and cannot exceed 100 days.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee. Must match the authenticated caller's own employee record.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":false,"description":"Start date of the range (format `Y-m-d`). Defaults to the first day of the current month.","schema":{"type":"string","format":"date"},"example":"2024-03-01"},{"name":"filter[to]","in":"query","required":false,"description":"End date of the range (format `Y-m-d`). Defaults to today. The range may not exceed 100 days.","schema":{"type":"string","format":"date"},"example":"2024-03-31"}],"responses":{"200":{"description":"OK. Flat object keyed by week-start date (`YYYY-MM-DD`) plus a reserved `summary` key. NOT wrapped in `data`.\n","content":{"application\/json":{"schema":{"type":"object","description":"Map keyed by week-start date plus a reserved `summary` key.","additionalProperties":{"type":"object","description":"Aggregated work-time figures for a single week or the range summary.","properties":{"totalWorkedTime":{"type":"string","description":"Total worked time, formatted as `HH:MM:SS` (hours may exceed two digits).","example":"40:00:00"},"totalWorkedTimeSeconds":{"type":"integer","description":"Same figure in seconds.","example":144000},"requiredWorkedTime":{"type":"string","description":"Minimum required worked time as `HH:MM:SS`, or `-` when no work shift was compiled.","example":"40:00:00"},"requiredWorkedTimeSeconds":{"type":"integer","description":"Same figure in seconds; `0` when `requiredWorkedTime` is `-`.","example":144000},"businessDaysWorkedTime":{"type":"string","description":"Overtime balance on business days as `HH:MM:SS`, or `-` when no work shift was compiled. **Signed**: a week below the required time is negative (`-02:08:49`), so the weekly rows sum to the range total.\n","example":"-02:08:49"},"businessDaysWorkedTimeSeconds":{"type":"integer","description":"Same balance in seconds, negative for undertime; `0` when `businessDaysWorkedTime` is `-`. Sum this field rather than parsing the string.\n","example":-7729},"nonWorkingDaysWorkedTime":{"type":"string","description":"Overtime balance on non-working days as `HH:MM:SS` (signed), or `-` when no work shift was compiled.","example":"00:00:00"},"nonWorkingDaysWorkedTimeSeconds":{"type":"integer","description":"Same balance in seconds; `0` when `nonWorkingDaysWorkedTime` is `-`.","example":0},"hasOvertime":{"type":"boolean","description":"Whether the week recorded any overtime.","example":false},"minWorkTimeReached":{"type":"boolean","description":"Whether total worked time met or exceeded the required worked time.","example":true}}}},"example":{"2024-03-04":{"totalWorkedTime":"41:31:51","totalWorkedTimeSeconds":149511,"requiredWorkedTime":"40:00:00","requiredWorkedTimeSeconds":144000,"businessDaysWorkedTime":"01:31:51","businessDaysWorkedTimeSeconds":5511,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":true,"minWorkTimeReached":true},"2024-03-11":{"totalWorkedTime":"37:51:11","totalWorkedTimeSeconds":136271,"requiredWorkedTime":"40:00:00","requiredWorkedTimeSeconds":144000,"businessDaysWorkedTime":"-02:08:49","businessDaysWorkedTimeSeconds":-7729,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":false,"minWorkTimeReached":false},"summary":{"totalWorkedTime":"79:23:02","totalWorkedTimeSeconds":285782,"requiredWorkedTime":"80:00:00","requiredWorkedTimeSeconds":288000,"businessDaysWorkedTime":"-00:36:58","businessDaysWorkedTimeSeconds":-2218,"nonWorkingDaysWorkedTime":"00:00:00","nonWorkingDaysWorkedTimeSeconds":0,"hasOvertime":false,"minWorkTimeReached":false}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record, belongs to a different PBX, or requested an employee other than their own.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/required-work-time":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusWorkTimes"],"summary":"Get daily required work time for a single employee (user)","operationId":"tempusGetUserRequiredWorkTime","description":"Returns the contracted (required) work time per calendar day for one employee across the requested range. The response is a flat object (NOT wrapped in `data`) keyed by date (`YYYY-MM-DD`); each value is the required work time for that day in seconds. The figure is derived from the employee's active work-shift assignment and is reduced by approved absences and public holidays (full-day holidays yield 0, half-day holidays halve the requirement). Values are never negative. Both `filter[from]` and `filter[to]` are required and the range may not exceed 100 days. The caller may only request their own employee record; requesting another employee returns 403.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee. Must match the authenticated caller's own employee record.","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":true,"description":"Start date of the range (format `Y-m-d`).","schema":{"type":"string","format":"date"},"example":"2024-03-01"},{"name":"filter[to]","in":"query","required":true,"description":"End date of the range (format `Y-m-d`). The range may not exceed 100 days.","schema":{"type":"string","format":"date"},"example":"2024-03-31"}],"responses":{"200":{"description":"OK. Flat object keyed by date (`YYYY-MM-DD`); each value is the required work time in seconds for that day. NOT wrapped in `data`.\n","content":{"application\/json":{"schema":{"type":"object","description":"Map keyed by date. Each value is the required work time for that day in seconds.","additionalProperties":{"type":"integer","description":"Required work time for the day in seconds (never negative).","example":28800}},"example":{"2024-03-01":28800,"2024-03-02":0,"2024-03-03":0,"2024-03-04":28800,"2024-03-05":14400}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no associated employee record, belongs to a different PBX, or requested an employee other than their own.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/groups":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusEmployees"],"summary":"List departments for the tenant (user)","operationId":"tempusListDepartments","description":"Returns a paginated list of departments (also called groups) belonging to the PBX tenant. Each item is serialized by the V1 `TempusDepartmentResource`. Departments are a per-tenant catalog of organizational units used across the Tempus time and attendance module. The authenticated user must belong to the PBX identified by the path parameter, otherwise the request is rejected with 403. Results are paginated using standard Laravel pagination.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100},"example":15}],"responses":{"200":{"description":"Paginated list of departments.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusDepartment"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user does not belong to the requested PBX tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/departments":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusEmployees"],"summary":"List departments for the tenant (user)","operationId":"listDepartments","description":"Returns the full list of departments belonging to the PBX tenant, each serialized by the V1 `DepartmentResource` with clean field names (id, name, description). Departments are a per-tenant catalog of organizational units used across the Tempus time and attendance module. The authenticated user must belong to the PBX identified by the path parameter, otherwise the request is rejected with 403. The result is not paginated: the complete list is returned as a top-level array. This is the properly named replacement for the legacy `groups` endpoint, which returns the same records under legacy key names.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"}],"responses":{"200":{"description":"List of departments.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusDepartmentBasic"}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user does not belong to the requested PBX tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/timepoints":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusEmployees"],"summary":"List timepoints for an employee (user)","operationId":"tempusListUserTimepoints","description":"Returns a paginated list of clock-in\/clock-out timepoints recorded for a single employee, newest first. The authenticated user must have access to the PBX tenant and be authorized to view the target employee's records. An optional date window can be applied with `filter[from]` and `filter[to]`; when both are supplied, `filter[from]` must not be after `filter[to]` and the range may not exceed 100 days, otherwise the request is rejected with 422. Each item is returned in the legacy timepoint shape (id, ext_id, time, status, comment, GPS coordinates, and an optional sub-status).\n\nThree independent pieces of location data are returned and must not be conflated: `location` is the configured location record the employee selected; `gpsLat` \/ `gpsLong` \/ `gpsTimestamp` and the normalised `device_gps` block are where the device said it was, stored exactly as the client reported it; `location_check` compares the two and carries the geofence verdict (`match` \/ `mismatch` \/ `unknown`). The device coordinates are never replaced by the coordinates configured on the location.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee whose timepoints are listed.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"filter[from]","in":"query","required":false,"description":"Return timepoints whose start time is on or after this date (Y-m-d).","schema":{"type":"string","format":"date"},"example":"2026-01-01"},{"name":"filter[to]","in":"query","required":false,"description":"Return timepoints whose start time is on or before this date (Y-m-d).","schema":{"type":"string","format":"date"},"example":"2026-01-31"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":500},"example":15}],"responses":{"200":{"description":"Paginated list of employee timepoints.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusUserTimepointLegacy"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user has no access to this PBX tenant or is not authorized to view the target employee's records.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/user\/{employee_id}\/timepoints\/{id}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"delete":{"tags":["TempusEmployees"],"summary":"Delete a timepoint for an employee (user)","operationId":"tempusDeleteUserTimepoint","description":"Permanently deletes a single timepoint belonging to the specified employee within the PBX tenant. The timepoint must exist for the tenant and must belong to the given employee, otherwise a 404 is returned. The authenticated user must be authorized by the timepoint delete policy for this tenant; if not, a 403 is returned.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"employee_id","in":"path","required":true,"description":"UUID of the employee that owns the timepoint.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"id","in":"path","required":true,"description":"UUID of the timepoint to delete.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440070"}],"responses":{"204":{"description":"Timepoint deleted. No content is returned."},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is not authorized to delete this timepoint."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/schedules":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"List schedules for the tenant (user)","operationId":"tempusListSchedules","description":"Returns a paginated list of active Tempus schedules (planning grids) for the PBX tenant. Only schedules whose owning department belongs to the tenant and whose `is_active` flag is true are returned, ordered alphabetically by name. Each item is a `TempusScheduleSummary` as serialized by the `ScheduleResource`, with its owning department embedded under the `group` key. Results can be narrowed to one or more departments with the `filter[group_id]` query parameter.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"filter[group_id]","in":"query","required":false,"description":"Comma-separated list of department (group) UUIDs to restrict results to. Only schedules belonging to these departments are returned.\n","schema":{"type":"string"},"example":"550e8400-e29b-41d4-a716-446655440002"},{"name":"page","in":"query","required":false,"description":"Page number to retrieve.","schema":{"type":"integer","minimum":1},"example":1},{"name":"per_page","in":"query","required":false,"description":"Number of items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":100},"example":100}],"responses":{"200":{"description":"Paginated list of active schedules for the tenant.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleSummary"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"List managed schedules for the tenant (user)","operationId":"tempusListManagedSchedules","description":"Returns a paginated list of the tenant's schedules. Reading is open to any authenticated user of the PBX; write access stays gated by the caller's schedules-management validator scope. Use the `search` parameter to filter by schedule name and `is_active` to filter by active state.\n\nEach item carries its scope: `scopeType` plus the raw `scope` selection, the resolved `departments`, and the `employees` who may be booked into its slots.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"search","in":"query","required":false,"description":"Filter schedules whose name contains this string.","schema":{"type":"string","maxLength":200},"example":"Reception"},{"name":"is_active","in":"query","required":false,"description":"Filter by active state. Accepts boolean-like values.","schema":{"type":"boolean"},"example":true},{"name":"per_page","in":"query","required":false,"description":"Number of items per page (capped at 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":15},"example":15}],"responses":{"200":{"description":"Paginated list of managed schedules.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleManagement"}},"links":{"type":"object","properties":{"first":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The first page of the resource"},"last":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The last page of the resource"},"prev":{"type":["null","string"],"example":null,"description":"The previous page of the resource"},"next":{"type":["null","string"],"example":null,"description":"The next page of the resource"}}},"meta":{"type":"object","properties":{"current_page":{"type":"integer","minimum":1,"example":1,"description":"The current page of the resource"},"from":{"type":["null","integer"],"minimum":1,"example":1,"description":"The first item of the resource"},"last_page":{"type":"integer","minimum":1,"example":1,"description":"The last page of the resource"},"links":{"type":"array","items":{"properties":{"url":{"type":["string","null"],"example":"http:\/\/localhost\/api\/v1\/resources?page=1","description":"The url of the resource (null for the boundary prev\/next links)"},"label":{"type":"string","example":"first","description":"The label of the resource"},"active":{"type":"boolean","example":true,"description":"The status of the resource"}},"type":"object"}},"path":{"type":"string","example":"http:\/\/localhost\/api\/v1\/resources","description":"The path of the resource"},"per_page":{"type":"integer","minimum":1,"example":15,"description":"The number of items per page of the resource"},"to":{"type":["null","integer"],"minimum":1,"example":1,"description":"The last item of the resource"},"total":{"type":"integer","minimum":0,"example":1,"description":"The total number of items of the resource"}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"post":{"tags":["TempusSchedules"],"summary":"Create a schedule (user)","operationId":"tempusCreateManagedSchedule","description":"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.\n\n`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.\n\nThe 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.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name","days_of_week","day_start_time","day_end_time"],"properties":{"name":{"type":"string","maxLength":150,"description":"Display name of the schedule.","example":"Reception weekdays"},"scope_type":{"type":"string","enum":["company","department","employees"],"default":"department","description":"Who the schedule is for. Optional: when omitted the request behaves exactly as before scopes existed and `department_id` becomes the scope.\n","example":"department"},"companies":{"type":"array","minItems":1,"description":"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.\n","items":{"type":"string","format":"uuid","description":"UUID of a company."},"example":["550e8400-e29b-41d4-a716-446655440020"]},"departments":{"type":"array","minItems":1,"description":"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.\n","items":{"type":"string","format":"uuid","description":"UUID of a department."},"example":["550e8400-e29b-41d4-a716-446655440001","550e8400-e29b-41d4-a716-446655440002"]},"employees":{"type":"array","minItems":1,"description":"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`.\n","items":{"type":"string","format":"uuid","description":"UUID of an employee."},"example":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]},"department_id":{"type":["string","null"],"format":"uuid","description":"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.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"days_of_week":{"type":"array","minItems":1,"description":"Weekdays the schedule covers.","items":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday number (1 = Monday through 7 = Sunday)."},"example":[1,2,3,4,5]},"day_start_time":{"type":"string","description":"Start of the daily window as `HH:MM`.","example":"08:00"},"day_end_time":{"type":"string","description":"End of the daily window as `HH:MM`. Must be after day_start_time.","example":"17:00"},"status_id":{"type":["string","null"],"format":"uuid","description":"Default status for generated entries. Must belong to your PBX.","example":"550e8400-e29b-41d4-a716-446655440003"},"sub_status_id":{"type":["string","null"],"format":"uuid","description":"Default sub-status. Must belong to the selected status.","example":null},"status_filters":{"type":"array","description":"Statuses selectable on the grid. Each must belong to your PBX.","items":{"type":"string","format":"uuid","description":"UUID of an allowed status."},"example":[]},"is_active":{"type":"boolean","default":true,"description":"Whether the schedule is active.","example":true}}},"examples":{"departmentScope":{"summary":"Several departments","value":{"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"}},"companyScope":{"summary":"Whole companies","value":{"name":"Group-wide on-call","scope_type":"company","companies":["550e8400-e29b-41d4-a716-446655440020"],"days_of_week":[1,2,3,4,5,6,7],"day_start_time":"00:00","day_end_time":"23:30"}},"employeeScope":{"summary":"A hand-picked team","value":{"name":"Weekend duty team","scope_type":"employees","employees":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"],"days_of_week":[6,7],"day_start_time":"09:00","day_end_time":"18:00"}},"legacySingleDepartment":{"summary":"Pre-scope request, still supported unchanged","value":{"name":"Reception weekdays","department_id":"550e8400-e29b-41d4-a716-446655440001","days_of_week":[1,2,3,4,5],"day_start_time":"08:00","day_end_time":"17:00"}}}}}},"responses":{"201":{"description":"The created schedule.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusScheduleManagement"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"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.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"Get a managed schedule (user)","operationId":"tempusGetManagedSchedule","description":"Returns the detail of a single schedule with its `department`, `status`, and `subStatus` relations resolved, plus its scope: `scopeType`, the raw `scope` selection, the resolved `departments`, and the `employees` who may be booked into its slots. Reading is open to any authenticated user of the PBX; a schedule in another tenant returns 404.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"The requested schedule.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusScheduleManagement"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}},"put":{"tags":["TempusSchedules"],"summary":"Update a schedule (user)","operationId":"tempusUpdateManagedSchedule","description":"Updates a schedule. Every field is optional: send only what changes. The caller must hold the schedules-management permission and manage at least some of the schedule's people; otherwise a 404 is returned.\n\nScope: send `scope_type` with the matching selection to change who the schedule is for. The new selection REPLACES the previous one. An update that mentions none of `scope_type`, `companies`, `departments`, `employees` or `department_id` leaves the scope exactly as it was, so a plain rename is safe. `day_start_time` and `day_end_time` must be sent together.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":150,"description":"Display name of the schedule.","example":"Reception (summer)"},"scope_type":{"type":"string","enum":["company","department","employees"],"description":"Change who the schedule is for. Send it together with the matching selection; the new selection REPLACES the old one, so switching a department schedule to `employees` drops its departments.\n","example":"employees"},"companies":{"type":"array","minItems":1,"description":"Companies the schedule covers. Required when `scope_type` is `company`.","items":{"type":"string","format":"uuid","description":"UUID of a company."},"example":["550e8400-e29b-41d4-a716-446655440020"]},"departments":{"type":"array","minItems":1,"description":"Departments the schedule covers. Used when `scope_type` is `department`.","items":{"type":"string","format":"uuid","description":"UUID of a department."},"example":["550e8400-e29b-41d4-a716-446655440001"]},"employees":{"type":"array","minItems":1,"description":"The exact people the schedule covers. Required when `scope_type` is `employees`.\n","items":{"type":"string","format":"uuid","description":"UUID of an employee."},"example":["550e8400-e29b-41d4-a716-446655440010"]},"department_id":{"type":["string","null"],"format":"uuid","description":"Move the schedule's anchor department. The target must be within your validator scope.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"days_of_week":{"type":"array","minItems":1,"description":"Weekdays the schedule covers.","items":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday number (1 = Monday through 7 = Sunday)."},"example":[1,2,3,4,5]},"day_start_time":{"type":"string","description":"Start of the daily window as `HH:MM`. Must be sent together with day_end_time.\n","example":"08:00"},"day_end_time":{"type":"string","description":"End of the daily window as `HH:MM`. Must be after day_start_time and sent together with it.\n","example":"17:00"},"status_id":{"type":["string","null"],"format":"uuid","description":"Default status for generated entries. Must belong to your PBX.","example":"550e8400-e29b-41d4-a716-446655440003"},"sub_status_id":{"type":["string","null"],"format":"uuid","description":"Default sub-status. Must belong to the selected status.","example":null},"status_filters":{"type":"array","description":"Statuses selectable on the grid. Each must belong to your PBX.","items":{"type":"string","format":"uuid","description":"UUID of an allowed status."},"example":[]},"is_active":{"type":"boolean","description":"Whether the schedule is active.","example":false}}},"examples":{"renameOnly":{"summary":"Rename, leaving the scope untouched","value":{"name":"Reception (summer)"}},"reScope":{"summary":"Switch to a hand-picked team, replacing the old selection","value":{"scope_type":"employees","employees":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]}}}}}},"responses":{"200":{"description":"The updated schedule.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusScheduleManagement"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller has no schedules-management scope, or the new selection reaches beyond it. The message is \"You do not have permission to manage schedules for this department.\" for a department (or one resolved from a selected company) outside the scope, and \"You do not have permission to manage this employee.\" for an employee outside it.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"patch":{"tags":["TempusSchedules"],"summary":"Partially update a schedule (user)","operationId":"tempusPatchManagedSchedule","description":"Updates a schedule. Every field is optional: send only what changes. The caller must hold the schedules-management permission and manage at least some of the schedule's people; otherwise a 404 is returned.\n\nScope: send `scope_type` with the matching selection to change who the schedule is for. The new selection REPLACES the previous one. An update that mentions none of `scope_type`, `companies`, `departments`, `employees` or `department_id` leaves the scope exactly as it was, so a plain rename is safe. `day_start_time` and `day_end_time` must be sent together.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":150,"description":"Display name of the schedule.","example":"Reception (summer)"},"scope_type":{"type":"string","enum":["company","department","employees"],"description":"Change who the schedule is for. Send it together with the matching selection; the new selection REPLACES the old one, so switching a department schedule to `employees` drops its departments.\n","example":"employees"},"companies":{"type":"array","minItems":1,"description":"Companies the schedule covers. Required when `scope_type` is `company`.","items":{"type":"string","format":"uuid","description":"UUID of a company."},"example":["550e8400-e29b-41d4-a716-446655440020"]},"departments":{"type":"array","minItems":1,"description":"Departments the schedule covers. Used when `scope_type` is `department`.","items":{"type":"string","format":"uuid","description":"UUID of a department."},"example":["550e8400-e29b-41d4-a716-446655440001"]},"employees":{"type":"array","minItems":1,"description":"The exact people the schedule covers. Required when `scope_type` is `employees`.\n","items":{"type":"string","format":"uuid","description":"UUID of an employee."},"example":["550e8400-e29b-41d4-a716-446655440010"]},"department_id":{"type":["string","null"],"format":"uuid","description":"Move the schedule's anchor department. The target must be within your validator scope.\n","example":"550e8400-e29b-41d4-a716-446655440001"},"days_of_week":{"type":"array","minItems":1,"description":"Weekdays the schedule covers.","items":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday number (1 = Monday through 7 = Sunday)."},"example":[1,2,3,4,5]},"day_start_time":{"type":"string","description":"Start of the daily window as `HH:MM`. Must be sent together with day_end_time.\n","example":"08:00"},"day_end_time":{"type":"string","description":"End of the daily window as `HH:MM`. Must be after day_start_time and sent together with it.\n","example":"17:00"},"status_id":{"type":["string","null"],"format":"uuid","description":"Default status for generated entries. Must belong to your PBX.","example":"550e8400-e29b-41d4-a716-446655440003"},"sub_status_id":{"type":["string","null"],"format":"uuid","description":"Default sub-status. Must belong to the selected status.","example":null},"status_filters":{"type":"array","description":"Statuses selectable on the grid. Each must belong to your PBX.","items":{"type":"string","format":"uuid","description":"UUID of an allowed status."},"example":[]},"is_active":{"type":"boolean","description":"Whether the schedule is active.","example":false}}},"examples":{"renameOnly":{"summary":"Rename, leaving the scope untouched","value":{"name":"Reception (summer)"}},"reScope":{"summary":"Switch to a hand-picked team, replacing the old selection","value":{"scope_type":"employees","employees":["550e8400-e29b-41d4-a716-446655440010","550e8400-e29b-41d4-a716-446655440011"]}}}}}},"responses":{"200":{"description":"The updated schedule.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TempusScheduleManagement"}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller has no schedules-management scope, or the new selection reaches beyond it. The message is \"You do not have permission to manage schedules for this department.\" for a department (or one resolved from a selected company) outside the scope, and \"You do not have permission to manage this employee.\" for an employee outside it.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["TempusSchedules"],"summary":"Delete a schedule (user)","operationId":"tempusDeleteManagedSchedule","description":"Soft-deletes a schedule and cascades to its slots. Refused with a 422 while the schedule still has assigned entries: clear those first. The caller must hold the schedules-management permission and manage at least some of the schedule's people.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"The schedule was deleted.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Confirmation message.","example":"Schedule deleted successfully."}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The caller has no schedules-management scope."},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"The schedule still has assigned entries. Body is `{\"message\": \"This schedule has assigned entries and cannot be deleted. Remove the entries first.\"}`.\n"}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/employees":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"List the employees a schedule may assign (user)","operationId":"tempusGetManagedScheduleEmployees","description":"Returns the people who may be booked into this schedule's slots: its scope resolved for you, whether that scope is whole companies, several departments, or a hand-picked list. Use it to populate the assignment dropdown on the slot create and edit forms. Booking anybody outside this list is refused with a 422.\n\nOnly employees holding a contract that is active today are listed, whatever the scope type \u2014 a hand-picked selection does not override the contract, so somebody who has left or has not started yet is left out.\n\nReading only requires a token belonging to the PBX, like the other schedule GET endpoints. The same list is embedded as `employees` on every schedule payload, so a client that already loaded the schedule does not need this call.\n\nThis replaces the former approach of calling `GET \/{pbx_id}\/users?filter[group_id]=<the schedule's group>`, which only ever worked for single-department schedules and under-reports for company and employee scoped ones.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"The employees the schedule may assign, ordered by name.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleEmployee"}}}},"example":{"data":[{"id":"550e8400-e29b-41d4-a716-446655440010","fullName":"Jane Smith","departmentId":"550e8400-e29b-41d4-a716-446655440002","departmentName":"Customer Support"},{"id":"550e8400-e29b-41d4-a716-446655440011","fullName":"John Baker","departmentId":null,"departmentName":null}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/calendar":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"Get the weekly calendar for a schedule (user)","operationId":"tempusGetScheduleCalendar","description":"Returns a weekly calendar view for the schedule, expanding its recurring slots and booked entries across a single week. The week begins on the Monday of the week containing `week_start`; when omitted it defaults to the current week. The schedule must belong to a department the authenticated user is allowed to manage.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"week_start","in":"query","required":false,"description":"ISO date used to select the week to render.","schema":{"type":"string","format":"date"},"example":"2026-03-02"},{"name":"employee_id","in":"query","required":false,"description":"Optional employee UUID to restrict the calendar to a single employee.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"}],"responses":{"200":{"description":"Weekly calendar for the schedule.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleCalendar"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/colors":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"get":{"tags":["TempusSchedules"],"summary":"List employee colors for a schedule (user)","operationId":"tempusListScheduleColors","description":"Returns the per-employee hex colors configured for a schedule. These colors are used to tint each employee's entries on the calendar grid. The schedule must belong to a department the authenticated user is allowed to manage.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"responses":{"200":{"description":"List of employee colors for the schedule.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"employeeId":{"type":"string","format":"uuid","description":"Identifier of the Tempus employee.","example":"550e8400-e29b-41d4-a716-446655440002"},"employeeName":{"type":["string","null"],"description":"Full name of the employee, or null when unresolved.","example":"Jane Smith"},"colorHex":{"type":"string","description":"Hex color assigned to the employee within this schedule.","example":"#4F46E5"}}}}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/colors\/{employee}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"put":{"tags":["TempusSchedules"],"summary":"Set an employee color for a schedule (user)","operationId":"tempusSetScheduleColor","description":"Creates or updates the hex color assigned to an employee within a schedule. The schedule must belong to a department the authenticated user manages, and the employee must be within the caller's schedules-management scope.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"employee","in":"path","required":true,"description":"UUID of the Tempus employee.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440002"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["color_hex"],"properties":{"color_hex":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","description":"Six-digit hex color string, including the leading hash.","example":"#4F46E5"}}}}}},"responses":{"200":{"description":"The color was created or updated.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Color updated."}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant or the employee is not within the caller's schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/slots":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusSchedules"],"summary":"Create a slot in a schedule (user)","operationId":"tempusCreateScheduleSlot","description":"Creates a recurring time slot within a schedule. The slot's start and end times must fall within the schedule's daily bounds, and the column index is assigned automatically when not supplied. The schedule must belong to a department the authenticated user is allowed to manage.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["start_time","end_time","recurrence_type","recurrence_start_date"],"properties":{"column_index":{"type":"integer","minimum":0,"maximum":99,"description":"Optional column index. Assigned automatically when omitted.","example":0},"start_time":{"type":"string","description":"Slot start time as `HH:MM`. Must be within the schedule bounds.","example":"09:00"},"end_time":{"type":"string","description":"Slot end time as `HH:MM`. Must be after start_time and within bounds.","example":"17:00"},"recurrence_type":{"type":"string","enum":["none","daily","weekly","custom"],"description":"Recurrence rule for the slot.","example":"weekly"},"recurrence_days":{"type":"array","description":"Weekday numbers the slot recurs on. Required when recurrence_type is weekly or custom.\n","items":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday number (1 = Monday through 7 = Sunday)."},"example":[1,2,3,4,5]},"recurrence_start_date":{"type":"string","format":"date","description":"First date the recurrence applies. Must be today or later.","example":"2026-03-02"},"recurrence_end_date":{"type":["string","null"],"format":"date","description":"Last date the recurrence applies. Must be on or after the start date.","example":"2026-12-31"},"recurrence_count":{"type":["integer","null"],"minimum":1,"maximum":730,"description":"Optional number of occurrences.","example":60}}}}}},"responses":{"201":{"description":"The slot was created.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleSlot"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management\/{schedule}\/slots\/{slot}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"put":{"tags":["TempusSchedules"],"summary":"Update a schedule slot (user)","operationId":"tempusUpdateScheduleSlot","description":"Updates an existing slot. Any subset of the slot fields may be supplied. Start and end times, when provided, must remain within the schedule's daily bounds. The schedule must belong to a department the authenticated user manages, and the slot must belong to that schedule.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"slot","in":"path","required":true,"description":"UUID of the slot.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"column_index":{"type":"integer","minimum":0,"maximum":99,"example":0},"start_time":{"type":"string","description":"Slot start time as `HH:MM`. Must be within the schedule bounds.","example":"09:00"},"end_time":{"type":"string","description":"Slot end time as `HH:MM`. Must be after start_time and within bounds.","example":"17:00"},"recurrence_type":{"type":"string","enum":["none","daily","weekly","custom"],"example":"weekly"},"recurrence_days":{"type":"array","description":"Required when recurrence_type is weekly or custom.","items":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday number (1 = Monday through 7 = Sunday)."},"example":[1,2,3,4,5]},"recurrence_start_date":{"type":"string","format":"date","description":"Must be today or later.","example":"2026-03-02"},"recurrence_end_date":{"type":["string","null"],"format":"date","example":"2026-12-31"},"recurrence_count":{"type":["integer","null"],"minimum":1,"maximum":730,"example":60},"is_active":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"The slot was updated.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleSlot"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}},"delete":{"tags":["TempusSchedules"],"summary":"Delete a schedule slot (user)","operationId":"tempusDeleteScheduleSlot","description":"Deletes a slot and all of its entries. The schedule must belong to a department the authenticated user manages, and the slot must belong to that schedule.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"schedule","in":"path","required":true,"description":"UUID of the schedule.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"slot","in":"path","required":true,"description":"UUID of the slot.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"}],"responses":{"204":{"description":"The slot and its entries were deleted."},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/schedule-management\/slots\/{slot}\/entries":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusSchedules"],"summary":"Create an entry in a slot (user)","operationId":"tempusCreateScheduleEntry","description":"Books an employee into a slot for a given time window. When `apply_to_all` is true the booking is applied across all occurrences of the recurring slot and a collection of entries is returned, optionally with a `warning` describing skipped occurrences; otherwise a single entry is returned. The employee must be within the caller's schedules-management scope, and the slot must belong to a schedule in a department the caller manages.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"slot","in":"path","required":true,"description":"UUID of the slot.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["employee_id","start_datetime","end_datetime"],"properties":{"employee_id":{"type":"string","format":"uuid","description":"UUID of the Tempus employee to assign.","example":"550e8400-e29b-41d4-a716-446655440002"},"start_datetime":{"type":"string","format":"date-time","description":"Entry start datetime, interpreted in the application timezone.","example":"2026-03-02T09:00:00"},"end_datetime":{"type":"string","format":"date-time","description":"Entry end datetime. Must be after start_datetime.","example":"2026-03-02T17:00:00"},"apply_to_all":{"type":"boolean","description":"Apply the booking to all occurrences of the recurring slot.","example":false},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional free-form note attached to the booking.","example":"Covering the morning desk"}}}}}},"responses":{"201":{"description":"The entry was created. Returns a single entry when apply_to_all is false, or a collection (optionally with a warning) when apply_to_all is true.\n","content":{"application\/json":{"schema":{"oneOf":[{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}},"warning":{"type":"string","description":"Summary of occurrences that were skipped.","example":"2 occurrences were skipped due to conflicts."}}}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, or the employee is not within the caller's schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Validation failed, or the employee is not part of the schedule. A schedule covers a set of companies, departments or hand-picked people, and only those may be booked into its slots: assigning anybody else returns `{\"message\": \"This employee is not part of the schedule. Pick one of the schedule's employees.\"}`. Take the assignable list from the schedule's `employees` field or from `GET \/{pbx_id}\/schedule-management\/{schedule}\/employees`.\n"}}}},"\/{pbx_id}\/schedule-management\/slots\/{slot}\/auto-assign":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"post":{"tags":["TempusSchedules"],"summary":"Auto-assign the best employee to a slot (user)","operationId":"tempusAutoAssignScheduleEntry","description":"Selects the most eligible employee for a slot over the given time window and books them into it, returning the created entry. The chosen employee must be within the caller's schedules-management scope; if no eligible in-scope employee is found a 404 is returned. The slot must belong to a schedule in a department the caller manages.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"slot","in":"path","required":true,"description":"UUID of the slot.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440003"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["start_datetime","end_datetime"],"properties":{"start_datetime":{"type":"string","format":"date-time","description":"Entry start datetime, interpreted in the application timezone.","example":"2026-03-02T09:00:00"},"end_datetime":{"type":"string","format":"date-time","description":"Entry end datetime. Must be after start_datetime.","example":"2026-03-02T17:00:00"}}}}}},"responses":{"201":{"description":"The entry was created for the auto-selected employee.","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"The slot was not found within the caller's scope, or no eligible in-scope employee could be assigned.\n"},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/{pbx_id}\/schedule-management\/entries\/{entry}":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"put":{"tags":["TempusSchedules"],"summary":"Update a schedule entry (user)","operationId":"tempusUpdateScheduleEntry","description":"Updates an existing entry. Any subset of the entry fields may be supplied. When `apply_to_all` is true the change is propagated across the recurring series and a collection is returned; otherwise a single entry is returned. When changing the employee, the new employee must be within the caller's schedules-management scope. The entry must belong to a schedule in a department the caller manages.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"entry","in":"path","required":true,"description":"UUID of the entry.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440004"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"employee_id":{"type":"string","format":"uuid","description":"UUID of the Tempus employee to assign.","example":"550e8400-e29b-41d4-a716-446655440002"},"start_datetime":{"type":"string","format":"date-time","description":"Entry start datetime, interpreted in the application timezone.","example":"2026-03-02T09:00:00"},"end_datetime":{"type":"string","format":"date-time","description":"Entry end datetime. Must be after start_datetime.","example":"2026-03-02T17:00:00"},"apply_to_all":{"type":"boolean","description":"Propagate the change across the recurring series.","example":false},"comment":{"type":["string","null"],"maxLength":1000,"description":"Optional free-form note attached to the booking.","example":"Covering the morning desk"}}}}}},"responses":{"200":{"description":"The entry was updated. Returns a single entry when apply_to_all is false, or a collection when apply_to_all is true.\n","content":{"application\/json":{"schema":{"oneOf":[{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}}}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, or the target employee is not within the caller's schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Validation failed, or the employee is not part of the schedule. A schedule covers a set of companies, departments or hand-picked people, and only those may be booked into its slots: assigning anybody else returns `{\"message\": \"This employee is not part of the schedule. Pick one of the schedule's employees.\"}`. Take the assignable list from the schedule's `employees` field or from `GET \/{pbx_id}\/schedule-management\/{schedule}\/employees`.\n"}}},"delete":{"tags":["TempusSchedules"],"summary":"Delete a schedule entry (user)","operationId":"tempusDeleteScheduleEntry","description":"Deletes an entry. When `apply_to_all` is true the entire recurring series is removed; otherwise only the single occurrence is deleted. The entry must belong to a schedule in a department the caller manages.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"entry","in":"path","required":true,"description":"UUID of the entry.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440004"}],"requestBody":{"required":false,"content":{"application\/json":{"schema":{"type":"object","properties":{"apply_to_all":{"type":"boolean","description":"Delete the entire recurring series rather than one occurrence.","example":false}}}}}},"responses":{"204":{"description":"The entry was deleted."},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}},"\/{pbx_id}\/schedule-management\/entries\/{entry}\/move":{"servers":[{"url":"https:\/\/cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus production API v1 server"},{"url":"https:\/\/staging-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus staging API v1 server"},{"url":"https:\/\/dev-cockpit.voxbi.com\/tempus\/api\/v1","description":"Tempus dev API v1 server"}],"patch":{"tags":["TempusSchedules"],"summary":"Move a schedule entry to a new time (user)","operationId":"tempusMoveScheduleEntry","description":"Reschedules an entry to a new start and end datetime. The move is rejected with 422 when the new window overlaps another booking for the same employee in the same department. When `apply_to_all` is false the moved occurrence is marked as an exception and a single entry is returned; when true the change is propagated across the recurring series and a collection is returned. The entry must belong to a schedule in a department the caller manages.\n","security":[{"bearerAuth":[]}],"parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"pbx_id","in":"path","required":true,"description":"UUID of the PBX tenant.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440000"},{"name":"entry","in":"path","required":true,"description":"UUID of the entry.","schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440004"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["start_datetime","end_datetime"],"properties":{"start_datetime":{"type":"string","format":"date-time","description":"New entry start datetime, interpreted in the application timezone.","example":"2026-03-03T09:00:00"},"end_datetime":{"type":"string","format":"date-time","description":"New entry end datetime. Must be after start_datetime.","example":"2026-03-03T17:00:00"},"apply_to_all":{"type":"boolean","description":"Propagate the move across the recurring series.","example":false}}}}}},"responses":{"200":{"description":"The entry was moved. Returns a single entry when apply_to_all is false, or a collection when apply_to_all is true.\n","content":{"application\/json":{"schema":{"oneOf":[{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/TempusScheduleEntry"}}}}]}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"The authenticated user is outside the requested tenant, has no associated employee record, or has an empty schedules-management scope.\n"},"404":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}},"422":{"description":"Unprocessable Parameters. This error is returned when a parameter is not valid.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"The given data was invalid."},"errors":{"type":"object","properties":{"filter":{"type":"array","items":{"type":"string"}},"sort":{"type":"array","items":{"type":"string"}},"page":{"type":"array","items":{"type":"string"}},"per_page":{"type":"array","items":{"type":"string"}}}}}},"example":{"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."]}}}}}}}},"\/call-flow-steps\/{id}":{"get":{"tags":["CallFlowSteps"],"summary":"Get a Call flow step","operationId":"getCallFlowStep","description":"Returns the call flow step identified by the path parameter. Multi-tenant scoping is\nenforced: the caller can only fetch resources within their own PBX.\n","parameters":[{"name":"accept","in":"header","schema":{"type":"string","example":"application\/json"}},{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"5XX":{"description":"Server error. An unexpected condition was encountered on the server and the\nrequest could not be completed. The body is a generic JSON envelope with a\n`message` field. The response is logged on the server side; quote the\nrequest URL + timestamp when reporting an issue.\n","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"exception":{"type":"string","description":"Only present in non-production environments."},"file":{"type":"string","description":"Only present in non-production environments."},"line":{"type":"integer","description":"Only present in non-production environments."}}},"example":{"message":"Server Error"}}}},"200":{"description":"OK","headers":{"Host":{"schema":{"type":"string","example":"cockpit.voxbi.com"}},"Date":{"schema":{"type":"string","example":"Mon, 16 Oct 2023 14:08:48 GMT"}},"Connection":{"schema":{"type":"string","example":"close"}},"Cache-Control":{"schema":{"type":"string","example":"no-cache, private"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"X-RateLimit-Limit":{"schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":59}},"Vary":{"schema":{"type":"string","example":"Origin"}}},"content":{"application\/json":{"schema":{"description":"A single step inside a call flow. Steps are evaluated in ascending `order`\nto drive how an inbound call is handled. The `type` field discriminates the\nshape of `options`: each variant below documents the keys carried in\n`options` for that particular step type. Variants with no configurable\nsettings (`hang_up`, `start_recording`, `answer`) use an empty options\nobject. The v1 API returns exactly these top-level fields on every variant:\n`id`, `pbx_id`, `call_flow_id`, `type`, `options`, `is_active`, `order`.\nMost ID references inside `options` are UUIDs of related resources (users,\ngroups, IVRs, queues, schedules, etc.) scoped to the same tenant.\n","oneOf":[{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ring_user)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ring_user"],"description":"Step type. For this variant it rings one or more cockpit users, SIP devices, or groups.","example":"ring_user"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings describing which targets to ring and for how long.","required":["duration"],"properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Ring duration in seconds before moving to the next step.","example":20},"also_ring_dialed_extension":{"type":"boolean","description":"When true, also rings the extension that was originally dialed.","example":false},"also_ring_everyone_in_the_user_group":{"type":"boolean","description":"When true, also rings every member of the dialed user's group.","example":false},"dial_mobile_twinnings":{"type":"boolean","description":"When true, also rings the mobile twinning numbers configured for the targets.","example":false},"missed_calls":{"type":"boolean","description":"When true, an unanswered call on this step counts as a missed call for the targets. Defaults to true.","example":true},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist played while ringing.","example":"550e8400-e29b-41d4-a716-446655440010"},"users":{"type":["array","null"],"description":"Identifiers of the users to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440011"]},"sip_devices":{"type":["array","null"],"description":"Identifiers of the SIP devices to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440012"]},"groups":{"type":["array","null"],"description":"Identifiers of the user groups to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440013"]},"tags":{"type":["array","null"],"description":"Identifiers of tags whose tagged users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440014"]},"locations":{"type":["array","null"],"description":"Identifiers of locations whose users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440015"]},"languages":{"type":["array","null"],"description":"Identifiers of languages used to select which users to ring.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440016"]},"pools":{"type":["array","null"],"description":"Identifiers of pools whose users should be rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440017"]},"statuses":{"type":["array","null"],"description":"Identifiers of Tempus statuses used to filter which users are rung.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440018"]},"pickup_lines":{"type":["array","null"],"description":"Identifiers of users whose calls may be picked up by this step.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440019"]},"sub_statuses":{"type":["object","null"],"description":"Map keyed by Tempus status UUID. Each value is the list of\nTempus sub-status UUIDs selected under that status.\n","additionalProperties":{"type":"array","items":{"type":"string","format":"uuid"}},"example":{"550e8400-e29b-41d4-a716-446655440018":["550e8400-e29b-41d4-a716-446655440020"]}}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ring_external_number)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ring_external_number"],"description":"Step type. For this variant it dials out to an external PSTN number.","example":"ring_external_number"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":1},"options":{"type":"object","description":"Settings describing the external number to dial.","properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Ring duration in seconds before moving to the next step.","example":30},"number":{"type":["string","null"],"description":"External destination number in E.164 format.","example":"+12125550100"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist played while ringing.","example":"550e8400-e29b-41d4-a716-446655440010"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (call_flow)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["call_flow"],"description":"Step type. For this variant it routes the call to another call flow or extension.","example":"call_flow"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":2},"options":{"type":"object","description":"Settings describing the destination and optional schedule.","required":["call_flow_or_extension"],"properties":{"call_flow_or_extension":{"type":"string","enum":["extension","call_flow"],"description":"Selects whether the call is routed to an extension or another call flow.","example":"call_flow"},"extension":{"type":["string","null"],"format":"uuid","description":"Identifier of the destination extension (used when routing to an extension).","example":"550e8400-e29b-41d4-a716-446655440030"},"call_flow":{"type":["string","null"],"format":"uuid","description":"Identifier of the destination call flow (used when routing to a call flow).","example":"550e8400-e29b-41d4-a716-446655440031"},"schedule":{"type":["string","null"],"format":"uuid","description":"Identifier of a schedule that gates when this routing applies.","example":"550e8400-e29b-41d4-a716-446655440032"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (go_to_ivr)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["go_to_ivr"],"description":"Step type. For this variant it hands the call off to an IVR menu.","example":"go_to_ivr"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying which IVR to enter.","properties":{"ivr":{"type":["string","null"],"format":"uuid","description":"Identifier of the IVR menu to enter.","example":"550e8400-e29b-41d4-a716-446655440040"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (enter_queue)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["enter_queue"],"description":"Step type. For this variant it parks the caller in a queue.","example":"enter_queue"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":1},"options":{"type":"object","description":"Settings identifying the queue and how long to wait.","properties":{"duration":{"type":"integer","format":"int32","minimum":1,"description":"Maximum time in seconds to keep the caller queued before moving on.","example":60},"queue":{"type":["string","null"],"format":"uuid","description":"Identifier of the queue to enter.","example":"550e8400-e29b-41d4-a716-446655440050"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (text_to_speech)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["text_to_speech"],"description":"Step type. For this variant it plays an announcement (sound file or synthesized speech).","example":"text_to_speech"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings describing the announcement source.","required":["announcement_type"],"properties":{"announcement_type":{"type":"string","enum":["sound_file","tts_tag","tts_message"],"description":"Selects the announcement source (a stored sound file, a TTS tag, or a free-text TTS message).","example":"tts_message"},"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the announcement sound file to play (used when announcement_type is sound_file).","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override. `null` (Auto) plays the variant for the\nlanguage detected\/inherited earlier in the call; otherwise an ISO-639-1 code\nforces that variant.\n","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"tts_tag":{"type":["string","null"],"description":"Predefined TTS tag identifying a templated message (used when announcement_type is tts_tag).","example":"greeting_morning"},"tts_message":{"type":["string","null"],"description":"Free-text message to synthesize and play (used when announcement_type is tts_message).","example":"Welcome to Customer Support."}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (change_ringtone_and_label)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["change_ringtone_and_label"],"description":"Step type. For this variant it overrides the ringtone and the caller display label.","example":"change_ringtone_and_label"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings overriding ringtone, label, and music on hold.","properties":{"ringtone":{"type":["string","null"],"enum":["alert-ring1","alert-ring2","alert-ring3","alert-ring4","alert-ring5","null"],"description":"Ringtone key to apply on the receiving device.","example":"alert-ring1"},"label":{"type":["string","null"],"description":"Display label shown to the called party for the incoming call.","example":"VIP"},"music_on_hold":{"type":["string","null"],"format":"uuid","description":"Identifier of the music-on-hold playlist to apply.","example":"550e8400-e29b-41d4-a716-446655440010"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (webhook)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["webhook"],"description":"Step type. For this variant it fires an outbound HTTP request mid-flow.","example":"webhook"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":2},"options":{"type":"object","description":"Settings describing the HTTP endpoint to call.","properties":{"url":{"type":["string","null"],"format":"uri","description":"HTTP(S) endpoint invoked when the step runs.","example":"https:\/\/cockpit.voxbi.com\/hooks\/call"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (send_to_email)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["send_to_email"],"description":"Step type. For this variant it emails a recording\/voicemail to recipients.","example":"send_to_email"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":3},"options":{"type":"object","description":"Settings describing the recording to attach and the recipients.","properties":{"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file (recording) to attach to the email.","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override; `null` (Auto) keeps the detected\/inherited language.","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"},"email":{"type":["string","null"],"format":"email","description":"Explicit recipient email address.","example":"support@example.com"},"email_user":{"type":["array","null"],"description":"Identifiers of users whose email addresses should receive the message.","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440011"]},"email_to_called_user":{"type":"boolean","description":"When true, also emails the user who was originally called.","example":false}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (conference_room)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["conference_room"],"description":"Step type. For this variant it drops the caller into a conference room.","example":"conference_room"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the conference room extension.","properties":{"extension":{"type":["string","null"],"format":"uuid","description":"Identifier of the extension hosting the conference room.","example":"550e8400-e29b-41d4-a716-446655440030"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ivr_extension)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ivr_extension"],"description":"Step type. For this variant it plays a sound and waits for IVR-style key input.","example":"ivr_extension"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the sound file to play.","properties":{"sound_file":{"type":["string","null"],"format":"uuid","description":"Identifier of the sound file to play before collecting input.","example":"550e8400-e29b-41d4-a716-446655440060"},"language":{"type":["string","null"],"description":"Announcement language override; `null` (Auto) keeps the detected\/inherited language.","enum":["en","de","fr","lb","es","it","pt","nl","pl","ru","tr","sv","da","no","fi","cs","sk","el","hu","ro","bg","hr","uk","ar","he","hi","ja","ko","zh","id","ms","th","vi",null],"example":"fr"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (multicast)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["multicast"],"description":"Step type. For this variant it pages a multicast (intercom) group.","example":"multicast"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the multicast group and access PIN.","properties":{"multicast_group":{"type":["string","null"],"description":"Name or identifier of the multicast paging group.","example":"paging-floor-1"},"multicast_pin":{"type":["string","null"],"description":"PIN required to join the multicast group.","example":"1234"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (ai_assistant)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["ai_assistant"],"description":"Step type. For this variant it hands the call off to a Smart IVR \/ AI agent.","example":"ai_assistant"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","description":"Settings identifying the AI provider and agent.","properties":{"ai_provider":{"type":"string","enum":["famulor"],"description":"AI provider backing the assistant.","example":"famulor"},"famulor_agent":{"type":["string","null"],"format":"uuid","description":"Identifier of the Famulor agent that handles the call.","example":"550e8400-e29b-41d4-a716-446655440070"}}}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (hang_up)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["hang_up"],"description":"Step type. For this variant it terminates the call. This step has no configurable options.","example":"hang_up"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":4},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (start_recording)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["start_recording"],"description":"Step type. For this variant it begins call recording. This step has no configurable options.","example":"start_recording"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}},{"type":"object","required":["id","pbx_id","call_flow_id","type","options","is_active","order"],"title":"CallFlowStep (answer)","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the call flow step","example":"550e8400-e29b-41d4-a716-446655440000","readOnly":true},"pbx_id":{"type":"string","format":"uuid","description":"Identifier of the PBX (tenant) this step belongs to","example":"550e8400-e29b-41d4-a716-446655440001"},"call_flow_id":{"type":"string","format":"uuid","description":"Identifier of the parent call flow that owns this step","example":"550e8400-e29b-41d4-a716-446655440002"},"type":{"type":"string","enum":["answer"],"description":"Step type. For this variant it explicitly answers the call. This step has no configurable options.","example":"answer"},"is_active":{"type":"boolean","description":"Whether the step is enabled. Disabled steps are skipped during call routing.","example":true},"order":{"type":"integer","format":"int32","minimum":0,"description":"Zero-based position of the step within its call flow. Steps run in ascending order.","example":0},"options":{"type":"object","additionalProperties":false,"description":"Empty options object (this step type has no settings)."}}}],"discriminator":{"propertyName":"type"}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","pbx_id":"550e8400-e29b-41d4-a716-446655440001","call_flow_id":"550e8400-e29b-41d4-a716-446655440002","type":"ring_user","options":{"duration":20,"also_ring_dialed_extension":false,"also_ring_everyone_in_the_user_group":false,"dial_mobile_twinnings":false,"missed_calls":true,"music_on_hold":"550e8400-e29b-41d4-a716-446655440000","users":["550e8400-e29b-41d4-a716-446655440000"],"sip_devices":["550e8400-e29b-41d4-a716-446655440000"],"groups":["550e8400-e29b-41d4-a716-446655440000"],"tags":["550e8400-e29b-41d4-a716-446655440000"],"locations":["550e8400-e29b-41d4-a716-446655440000"],"languages":["550e8400-e29b-41d4-a716-446655440000"],"pools":["550e8400-e29b-41d4-a716-446655440000"],"statuses":["550e8400-e29b-41d4-a716-446655440000"],"pickup_lines":["550e8400-e29b-41d4-a716-446655440000"]}}}}},"401":{"description":"Authorization Token Missing. This error is returned when the authorization token is missing.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Authorization Token is missing","description":"Error message"}}},"example":{"error":"Authorization Token is missing"}}}},"403":{"description":"Data Not Found. This error is returned when the requested data is not found.","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, must-revalidate"}},"Connection":{"schema":{"type":"string","example":"keep-alive"}},"Content-Type":{"schema":{"type":"string","example":"application\/json"}},"Vary":{"schema":{"type":"string","example":"Origin"}},"X-RateLimit-Limit":{"description":"Max requests allowed in the current rate-limit window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","example":57}}},"content":{"application\/json":{"schema":{"type":"object","description":"Data not found","properties":{"message":{"type":"array","items":{"type":"string"}}}},"example":{"message":["Data not found"]}}}}}}}}}