Skip to main content
Shared Line Appearance (SLA) is the deskphone-replacement pattern for receptionist and executive-assistant deployments: one named line is mirrored onto every phone on its roster, an inbound call rings all member devices at once, the first member to pick up owns the call, and anyone on the roster can move it onto their own device later. Law firms, clinics, and executive suites replacing a legacy key system (Cisco, Avaya, Mitel) reach for SLA first. Every part of the lifecycle is in the Voice → Shared lines API — creation, roster management, live status, and the grab action. Inbound routing to SLA is done per DID — see section 6. Everything on this page is inbound termination and device-to-device mediation; outbound calling is unaffected.

1. When to use SLA

Use a shared line when a team answers one identity together and anyone on the team may take over a live call:
  • Reception desk — the company’s main number rings on every device at the front desk; whoever is free answers.
  • Executive assistant — the exec’s line appears on the assistant’s phone; the assistant screens, answers, and can hand the call to the exec without a transfer sequence.
  • Coverage pairs — two agents covering the same window see the other’s line go busy and grab it when one steps away.
SLA is not a queue (no FIFO hold, agents answer simultaneously) and not a ring group (a ring group rings devices, but it has no shared busy indicator and no grab). If you need either of those, see Pick the right inbound routing for a DID for the alternative route types.

2. Create a shared line

Create the line first, then add members. POST /api/v1/voice/shared-lines requires a role with write access (owner, admin, or developer).
cURL
The 201 response returns the created line with an empty members array — note the id, it goes in every later call. GET /api/v1/voice/shared-lines lists lines with cursor pagination (cursor, limit 1–100, default 50) and a per-line memberCount; GET /:id returns one line with its full roster.

3. Manage the member roster

Members are the devices the line rings. POST /:id/members and DELETE /:id/members/:memberId are write paths (owner/admin/developer).
cURL
Shape rules enforced at write time:
  • A sip_extension member must reference a live SIP credential for your organization — an unknown username answers 422 naming the value. user_id members are not existence-checked upfront; the fork layer resolves them at call time.
  • Each member value can appear once per line — a double-add answers 409 (otherwise the fork would invite the same phone twice).
  • The roster is capped at 50 members — the 51st answers 409.
  • Removing the last member is allowed; the line simply rings nothing until you re-add one (the DID’s fallback route then covers it — see section 6).
Remove a member:
cURL
Delete returns 204. Deleting the whole line (DELETE /api/v1/voice/shared-lines/:id) removes its roster too — there is no soft delete.

4. Poll live status

GET /:id/status is a read-only, side-effect-free endpoint the Shared Lines dashboard page polls to draw the busy lamp and decide whether to offer Grab. Front-desk roles can read it (owner, admin, developer, agent).
cURL
200 — line idle
200 — line busy
activeCall semantics — the busy lamp is accurate on purpose:
  • activeCall: null means the line is idle. Only a call that actually arrived on the line (dialed to its primaryExtension, or arrives via a DID routed to this line) marks it busy. A member’s private or outbound call on their own phone never lights the line up.
  • onDeviceUsername is the SIP username of the member device currently holding the call. It is null when the line demonstrably has a call but the answering device hasn’t been correlated yet (mid-bridge) — the field is never a guess.
  • Poll on a short interval (the dashboard does); the endpoint is safe to hit repeatedly.

5. Grab an in-use call

Grab moves the line’s currently answered call from whichever device answered onto your own device — the receptionist-assistant handoff without a transfer menu. POST /:id/grab is a live-call action open to agent role as well as operators.
cURL
grabbingMemberValue must be a sip_extension member of this line’s roster with canGrab true — the receiving device, not the device that answered. The full walkthrough:
  1. Line is active (409 otherwise). An inactive line cannot be grabbed.
  2. You must be on the roster with grab permission (403). A grabbingMemberValue that isn’t a sip_extension member of this line, or has canGrab: false, is rejected with 403 — the membership flag is the gate, not just the roster.
  3. The line must have an answered call (404 otherwise). Grabbing while activeCall is null answers 404. Only a call on the line itself can be grabbed; a member’s private call is invisible to this endpoint, so a private call can never be pulled onto a colleague’s phone.
  4. You can’t grab the device already holding it (409). If onDeviceUsername was resolved and equals your grabbingMemberValue, the request is a no-op 409.
  5. Only one grabber wins (dedup). Claims race on a short atomic window, so two members hitting Grab in the same instant get one 200 and one 409. A retry of the same request id is equally safe — it reports conflict instead of double-moving the call.
A successful grab returns the resolved pair:
200
This endpoint resolves and claims the call; the call plane completes the actual SIP re-INVITE to move the media. Your device rings and the caller stays connected throughout.

6. Point a DID at the line

A shared line has no inbound traffic until a DID routes to it. On the number’s routing config, set type: "shared_line" with config.sharedLineId — the same picker under Numbers → number → Routing and the same API as every other route type (full guide: Pick the right inbound routing for a DID).
cURL
config.ringTimeoutSec is optional (5–120). Set a fallback so a call answers somewhere when the roster is empty or nobody picks up — route-specific notes on fallbacks are in the routing guide. Internal dials straight to the line’s primaryExtension also reach the line without touching a DID.

7. Errors and dedup semantics

The grab claim is atomic (a short-window dedup slot, same primitive used across the live-call endpoints), so safe-retry and racing-members semantics hold: one winner, conflict for the rest, and no double-move.
See also: Pick the right inbound routing for a DID · Extensions vs. Colleagues · Paging, ring groups, and call park