1. The concept: transient user-to-device binding
A session binds one user to one device for a bounded time. Enforcement is symmetric: one active session per device, and one per user, so the phone is never double-bound and the agent is never sitting at two desks at once. The binding is transient — it follows the person, not the hardware. What follows the user (attached to the device for the session):- Extension number and caller ID — outbound calls from the phone present the agent’s identity while signed in, and inbound calls to the agent’s extension ring that phone.
- Voicemail delivery — the agent’s mailbox applies for the session.
- Queue membership — the agent is reachable at this device for queue calls.
- The SIP registration — the phone keeps its own shared-pool credential (
acme-shared-5F-2-style), provisioned once under Voice → SIP credentials. - The shared-pool inbound rule — while signed out, inbound to the pool follows the device’s default inbound rule, so a phone never dangles without routing. See Hot-desking for device provisioning detail.
2. The sign-in / sign-out lifecycle
The session moves through a small state machine:signed_out, displaced_by_new_session, revoked, or expiry — which is what the admin list on Voice → Hot-desking shows.
Sign in (POST /api/v1/voice/hot-desking/sign-in):
- The agent opens Voice → Hot-desking, enters the device’s SIP username (label the physical phone with this), and an optional friendly label such as
Floor 5 — Desk 2. - An optional end-of-shift
expiresAt(up to 24h ahead) releases the session automatically — a backstop, not a guarantee. - If either party has an active session, the new sign-in displaces it atomically: signing in to a phone in use signs the prior agent out; signing in at a second phone signs the agent out of the first.
- Re-signing to the same device is a no-op — the existing session is re-confirmed rather than duplicated (the API responds
200instead of201).
POST /api/v1/voice/hot-desking/sign-out) is idempotent — a second sign-out does not error; it reports when the session actually ended (with the release reason), so a double-tapped button is harmless.
Revoke (POST /api/v1/voice/hot-desking/:id/revoke) — owner/admin force-release. Use it for a terminated employee or a lost device from the same dashboard page.
If two sign-ins collide for the same device or user, one wins and the other is asked to retry with a 409 — the winner holds the device.
3. The reservation calendar
Beside the walk-up board, Voice → Hot-desking has a booking calendar that reserves a specific desk for a future window — the model Cisco UCM, RingCentral, and 8x8 all ship on top of extension mobility. The calendar enforces single-booking: two overlapping windows for the same device can never both exist. Recurring shifts vs ad-hoc visits. There is no first-class “recurring reservation” object — a recurring roster needs one reservation per shift window: either duplicate the booking on the dashboard each week, or submit one API call per shift (a loop in your scheduling integration) with the samedeviceSipUsername. An ad-hoc visit is just a single one-off window — book it the same way. Either way you get the same conflict safety: the 409 double-booking rejection guarantees only one reservation holds the desk across any time slot.
Book (POST /api/v1/voice/hoteling/reservations) with deviceSipUsername, startsAt, endsAt (ISO-8601), and an optional notes. Limits: window ≤ 24 hours, start ≤ 90 days ahead, end must be after start. Attempting a window that overlaps an existing active reservation answers 409 HOTELING_DOUBLE_BOOKED, with the conflicting reservation returned under error.details.conflict so you can show who booked first.
List (GET /api/v1/voice/hoteling/reservations) scopes the agenda to ?scope=me (default) or ?scope=team, with optional from/to and deviceSipUsername filters. The dashboard toggle Mine / Team maps directly onto scope.
Cancel (DELETE /api/v1/voice/hoteling/reservations/:id) — the booker cancels their own reservation; owner/admin can cancel any.
Release — two automatic paths keep desks from dead-locking:
- No-show: if the booker hasn’t signed in 15 minutes after their window starts, the reservation releases and the desk becomes walk-up again. Until that grace runs out, a different agent signing in to the reserved desk is rejected.
- Elapsed sweep: windows that have fully elapsed flip to
expiredon every read/book. Owner/admin can force it now withPOST /api/v1/voice/hoteling/reservations/sweep.
4. Conflict prevention and clear priority
Conflict resolves deterministically at booking time — not at sign-in time:
The dashboard’s Team scope is the disagreement-settler: if a booking “isn’t mine,” that view answers who holds it.
5. Security boundary
Sign-in identifies who is at the device; it does not create the agent’s authentication. The session ledger records who, where (device SIP username), and when, and every transition lands in the audit log with actor, device, and timestamps.- Role-gated access. The page is visible to members with the
agentrole or above; revoke requiresowner/admin. Customers decide who may sign in or look by assigning roles — this is entirely tenant-managed. - Calls remain authenticated. The call itself rides the SIP credential the phone registered with (the shared-pool credential), so sign-in never carries the agent’s own SIP secret to the device, and the post-release device has no residual access to the user’s identity.
- Grace is a release, not a bypass. The 15-minute no-show grace only unlocks a walk-up; it never skips authentication.
- Emergency calling is unchanged. Orbit routes no emergency calls, hot-desking or not, so follow Emergency calling regardless of who is signed in.
6. Worked example: staffing a rotating-shift call center
A support floor runs three daily shifts (07:00–15:30, 15:00–23:30, 23:00–07:30) on 40 shared phones with 54 agents on the roster. No agent owns a desk; the pool absorbs shift swap without hardware changes. Sample calendar walk-through (one desk,acme-shared-5F-2, booked by the team planner via the API — the same thing the dashboard form does):
cURL
fulfilled. At 15:04 agent A forgets to sign out; agent B’s 15:00 reservation lives in the system, so B’s sign-in displaces A — release reason displaced_by_new_session in the ledger. One phone, three owners per day, zero re-provisioning.
If your shift rota feeds from an external scheduler, generate daily bookings with a loop over the agent/date pairs — the 409 on overlap acts as your safety net against a mis-scripted roster import.
Tips
Troubleshooting
Stuck session — an agent left without signing out: open Voice → Hot-desking, find the row, and revoke. With an expiry set this clears itself. “A concurrent sign-in beat this one” — two people signed in at the same moment; retry. Whoever signs in last holds the device. Sign-in blocked by a reservation — the desk is held for a booker still inside the no-show grace. Either wait out the 15 minutes, pick another desk, or ask an admin to cancel the reservation if the booker is a genuine no-show. Double-booking (409 HOTELING_DOUBLE_BOOKED) — the response names the conflicting reservation under error.details.conflict; show that to the booker instead of guessing. If a script imports a roster, fix the overlapping rows upstream.
Related references
- Hot-desking concept page — device provisioning and the sign-in state machine detail
- Voice hot-desking API reference — full field-level reference for the endpoints used above
- Audit log — where every session and reservation transition is recorded
- Emergency calling
- Holiday and closure calendars for inbound voice — the related calendar for routing, separate from desk reservations