Custom Wallboards /api/queue-status

The built-in wallboards cover most needs, but if you want a display that matches your branding — or shows exactly the metrics you care about — you can build your own on top of one simple endpoint: GET /api/queue-status. Poll it every few seconds and render the result however you like.

The endpoint

GET /api/queue-status returns a live snapshot of every open queue. It's a read-only status feed meant for on-LAN displays, so it needs no token — just make sure the display device can reach the PBX's web port (8084 / 8085).

curl https://your-pbx:8085/api/queue-status

Response

{
  "server": "VoicerOnePBX",
  "generatedAt": "2026-07-24T16:00:00Z",
  "queues": [
    {
      "id": "support",
      "name": "Support",
      "open": true,
      "waiting": 3,                    // callers waiting right now
      "longestWaitSeconds": 92,        // how long the front caller has waited
      "agents": { "available": 2, "busy": 4, "total": 6 },
      "agentDetail": [
        { "extension": "101", "state": "available" },
        { "extension": "102", "state": "busy" }
      ]
    }
  ]
}

Example 1 — poll it from anywhere

Any language can read it. A tiny loop that prints the numbers:

import time, urllib.request, json

while True:
    data = json.load(urllib.request.urlopen("https://your-pbx:8085/api/queue-status"))
    for q in data["queues"]:
        print(f'{q["name"]:12} waiting={q["waiting"]:2}  '
              f'longest={q["longestWaitSeconds"]:3}s  '
              f'agents {q["agents"]["available"]}/{q["agents"]["total"]} free')
    time.sleep(3)

Example 2 — a drop-in HTML wallboard

Save this as a single .html file and open it full-screen on any wall-mounted browser or media player. It refreshes every 3 seconds and turns a queue red when callers wait too long — no build step, no dependencies.

<!doctype html>
<html><head><meta charset="utf-8"><title>Queue Wallboard</title>
<style>
  body{margin:0;background:#0b1220;color:#e6edf6;font-family:system-ui,sans-serif}
  h1{padding:20px 28px;margin:0;font-size:22px;color:#93a4bd;font-weight:600}
  .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:20px;padding:0 28px 28px}
  .card{background:#0f1a2e;border:1px solid #1e2a44;border-radius:16px;padding:24px}
  .card.alert{border-color:#ef4444;box-shadow:0 0 0 2px rgba(239,68,68,.3)}
  .name{font-size:26px;font-weight:700;margin-bottom:14px}
  .row{display:flex;justify-content:space-between;font-size:20px;margin:8px 0}
  .big{font-size:64px;font-weight:800;line-height:1}
  .muted{color:#93a4bd;font-size:14px}
</style></head><body>
  <h1>Live Queue Status</h1>
  <div class="grid" id="board"></div>
<script>
const PBX = "https://your-pbx:8085";        // <- your PBX address
const ALERT_WAIT = 60;                       // seconds before a queue flashes red

async function tick() {
  try {
    const data = await (await fetch(PBX + "/api/queue-status")).json();
    document.getElementById("board").innerHTML = data.queues.map(q => `
      <div class="card ${q.longestWaitSeconds >= ALERT_WAIT ? "alert" : ""}">
        <div class="name">${q.name}</div>
        <div class="big">${q.waiting}</div>
        <div class="muted">callers waiting</div>
        <div class="row"><span>Longest wait</span><strong>${q.longestWaitSeconds}s</strong></div>
        <div class="row"><span>Agents free</span><strong>${q.agents.available}/${q.agents.total}</strong></div>
      </div>`).join("");
  } catch (e) { /* PBX unreachable — keep the last frame */ }
}
tick(); setInterval(tick, 3000);
</script>
</body></html>
Make it yours

From here it's just HTML and data: add your logo, show agentDetail as a live agent grid, sum waiting across queues for a headline number, or push the figures onto a TV via a Raspberry Pi in kiosk mode. The endpoint gives you the raw truth; the display is entirely up to you.

On the network

Because it needs no token, keep /api/queue-status on your trusted LAN (a wall display doesn't leave the building). Everything else in the API uses the Bearer token.