Skip to main content

BLF presence

Busy Lamp Field (BLF) presence is the live busy/idle view of your organization’s extensions: who is on a call right now, whose phone is ringing, who has do-not-disturb on, and whose device went quiet. It is the same lamp pattern a desk phone lights next to a watched extension, exposed as a REST + server-sent-events (SSE) surface you can build against from a wallboard, a receptionist console, or any custom roster UI. Every response is scoped to the organization that authenticates the request. One organization’s roster never appears in another organization’s snapshot or stream.

What BLF presence is (and what it is not)

BLF presence describes the telephony line, not the contact-center agent. Agent presence (available, auxiliary codes, shrinkage) answers “can this agent take work right now?” and feeds routing decisions. BLF presence answers “is this line free?” and is derived from three facts the platform already maintains for every SIP extension:
  • whether the extension’s device is currently registered, and how fresh that registration is,
  • whether do-not-disturb is switched on for the extension,
  • whether a call involving the extension is ringing or in progress.
Use agent presence for staffing and routing views. Use BLF presence whenever the state of the line is what matters: before offering a transfer, on a front-desk screen, or on a team wallboard.

The two consumption paths

Both paths return the same envelope:
states holds one entry per SIP extension in your organization; emittedAt stamps when the snapshot was derived. When you poll, treat emittedAt as the freshness marker.

The state entry

Wire state values

Poll or subscribe?

Poll the snapshot when a few seconds of staleness is fine and you want the simplest possible client: a server-side cron that writes to a badge system, a wallboard that refreshes on a timer, an admin script. Subscribe to the stream when a person is watching and the lamp must flip as the call flips: receptionist consoles, supervisor wallboards, in-browser rosters. The stream removes both the polling load and the polling lag.

Freshness: instant push with a 3-second safety net

The stream is event-driven first. Whenever a call involving one of your extensions starts, rings, or ends, the change is published on an organization-scoped notification channel and every open stream for your organization wakes up immediately and re-derives a full snapshot. In practice an active call transition reaches an open stream in well under a second. On top of that, each stream runs an independent reconciliation tick every 3 seconds that re-derives the snapshot from the source of truth. If a pushed wake-up is ever lost, the tick catches the missed transition within 3 seconds, so the stream self-heals without any action from you. Every frame carries a full snapshot, never a delta. There is no event ordering to maintain and no replay to request: any single frame, including the first one after a reconnect, is a complete current view of your roster.

Limits and connection behaviour

  • 100 concurrent streams per organization, enforced across the whole cluster. A 101st concurrent connection receives HTTP 429 with the error code TOO_MANY_CONNECTIONS. If your deployment needs more concurrent viewers than that, hold one stream in a backend and fan out to your clients from there.
  • Keepalive comments every 15 seconds. A line reading : ping keeps proxies and load balancers from idling the connection out. SSE clients ignore comment lines automatically; a hand-rolled parser must skip them.
  • 30-minute maximum stream duration. The server closes the stream cleanly after 30 minutes. This is expected, not an error: reconnect, as in the pattern below. Size any client-side idle timeout above the 15s keepalive cadence, not above the 30-minute ceiling.
  • Frames arrive as unnamed events. Each update is a single data: line holding the {states, emittedAt} JSON envelope. With EventSource that means onmessage; there are no named event types to register listeners for.
  • Browser origins are checked. A browser connect from an origin that is not trusted for your organization receives HTTP 403.

Examples

Fetch a snapshot

Subscribe from a browser (EventSource)

EventSource cannot set request headers, so pass your credential as the token query parameter, the same affordance the log stream exposes:

Subscribe from Node

From a server you can send the Authorization header directly and parse frames yourself. Frames are separated by a blank line; skip comment lines:

A full SSE frame

This is exactly what arrives on the wire: one data: line with the complete envelope, and periodic : ping comments in between:

Watch a single extension

Every frame is a full roster, so filtering is a client-side one-liner:

Reconnect with backoff

Streams end by design after 30 minutes, and any network can drop a connection at any moment. Treat every close as “reconnect”, with capped exponential backoff so a fleet of wallboards does not retry in lockstep:
Because every frame is a full snapshot, the first frame after a reconnect is already the complete current roster; you do not need to fetch a baseline separately.

Common topologies

Desk-phone roster. Hard-phone BLF keys (Polycom, Yealink, and similar) are provisioned per device and light their lamps over SIP; the organization-curated BLF and speed-dial list is configured under channel settings, see Channel settings consoles and Desk phone provisioning. Use the REST + SSE surface documented here for everything browser- or server-side: softphone rosters, custom consoles, wallboards. Supervisor wallboard. Hold one SSE stream per wallboard client (or one backend stream fanned out to many screens) and render each state as a lamp: green for idle, flashing for early, solid red for confirmed, grey for away / disabled. Pair it with queue metrics from Supervisor live monitoring for a complete floor view. Receptionist console. Sort the roster by extensionNumber and render label next to each lamp so the front desk can see at a glance who can take the next transfer. The in-product Attendant console renders the same states; this API is what you build against when you need a custom layout. There is no webhook or third-party push delivery for BLF presence. The subscription model is SSE only; if your architecture needs server-to-server fan-out, hold a single stream in your backend and republish to your internal consumers from there.

Cross-references

  • Voice supervisor plane model: how supervisor surfaces (wallboards, monitoring, coaching) fit together.
  • Supervisor live monitoring: queue- and agent-level live views that complement the line-level view on this page.
  • Colleagues: the in-product directory built on the same snapshot and stream.
  • Extensions: create, disable, and manage the SIP extensions that populate the roster, including each extension’s do-not-disturb switch.