A real-time health and call-volume dashboard for the external SIP trunks of a
Genesys Cloud CX organisation. A 5-second REST metrics poll is fused with the Genesys notifications
WebSocket, so charts advance on a steady clock while trunk up/down transitions land in sub-second
time — with an audited event log, chart annotations at the exact moment of each transition, and
PNG export for incident evidence.
Continuously integrated and updated. This is a published sample of the user guide. The App Suite changes frequently, so this page may not reflect the latest features, screens and behaviour. The current guide is available in the application through the QVCCS apps portal, included with every Managed Professional Services tier.
At a glance
live health + call volume
external SIP trunks
5 s poll + live push
multi-user
no database
strictly read-only
Security at a glance
Trunk Monitor
Read-only (manages only its own notification channel)
Sign-in
OAuth client credentials you supply; held on the server for your session only and never sent to the browser
Stores
Nothing at rest; sessions and chart history exist only while you are signed in
Trunk Monitor watches the external SIP trunks of a Genesys Cloud CX org in real time.
For every monitored trunk it shows two things:
Health — connected / disconnected state per edge instance, edge state and OPTIONS-ping
status, with an audited event log and chart annotations for every transition.
Live utilisation — active inbound and outbound call counts, charted on a rolling
5-minute window and a zoomable session-history chart (up to 3 hours).
It exists to answer operational questions instantly: Is the carrier trunk down? Did calls
drain to the backup trunk during the incident? What was our concurrent-call peak this
afternoon?
Which trunks appear is decided once, at sign-in (the inclusion rules, §4): all
EXTERNAL trunks, plus any PHONE trunks whose name matches the
optional phone-trunk name filter set for your deployment; EDGE trunks (inter-edge ties) are always excluded.
If nothing matches, the app falls back to showing every non-EDGE trunk and says so in the event
log.
Read-only posture: the app only ever issues Genesys reads plus the
notification-channel management calls (create channel / set subscriptions / clear subscriptions).
It never modifies telephony configuration, and there is no database — everything is held only for the lifetime of your session.
2Quick start
Open the app — you land on the sign-in page.
Sign in — pick the org’s home Region (14 regions),
enter the Client ID and Client Secret of an OAuth client-credentials client
The client’s role needs the Telephony read permission — see §5.
Watch — the app loads every trunk page-by-page, applies the inclusion rules and
drops you on the dashboard already populated. First metrics arrive within one 5-second poll; no
interaction is needed from then on.
Work the incident — click sidebar groups to hide/show them on the charts, wheel/pinch-zoom
the history chart into the incident window, and export either chart as a PNG (annotations
included) for the timeline write-up.
Client ID and region are remembered in your browser for next time;
the secret never is. Disconnect in the topbar signs you out fully and releases the session’s
Genesys notification channel.
One tab per session: the dashboard has a single live connection per session. Reloading the page (or closing the tab) closes that connection, and the app treats it as a sign-out — the whole session is cleaned up and you are returned to the sign-in page (with region and client
ID pre-filled, so re-entry is just the secret). Opening the dashboard in a second tab steals the
feed from the first.
3UI walkthrough
Sign-in page
Region dropdown, Client ID, Client Secret. Failed sign-ins return to the sign-in page with the Genesys error shown inline — a 401 means bad credentials while a 5xx points at Genesys or the network. The last-used client ID + region are restored from your browser; the secret is never stored anywhere in the
browser.
Topbar & status chips
org — the first 8 characters of your client ID (the dashboard never sees credentials) · region — the region you
signed into.
WS chip — your browser’s live feed and the Genesys-side notification socket share this
chip: WS Live (green), WS Dropped / WS Error (amber), WS Closed / WS Idle
(grey).
Connected chip — session state.
📖 Guide (this page) · Debug (a diagnostic view of your own session, for QVCCS support) · Disconnect (full sign-out).
KPI strip
Six live tiles: Trunks (number of trunk groups, see sidebar), Connected
(groups with every edge instance up — a “N partial” subtitle appears when some group is half-up),
Disconnected (fully-down plus partial groups — anything not fully healthy counts
here), Inbound Calls and Outbound Calls (active now, summed across visible readings),
and Last Poll (wall-clock of the newest data). KPIs update instantly on pushed events;
they never wait for the next poll.
Trunk sidebar
Grouping — Genesys creates one trunk object per edge instance, named
“Base name Trunk <uuid>”. The sidebar strips that suffix and groups by
base name, so a trunk with two edge instances shows as one card with a “2 edges”
badge.
Per card — colour swatch (matches the chart lines), name, a mini sparkline of
the last 20 inbound readings, live in/out counters, and a health dot: green (all instances up),
amber (partial), red (all down). A second row shows the trunk type badge
(External / Phone / Edge / Other), the edge-instance count and the state string
(ACTIVE / x/N UP / DOWN).
Ordering — cards sort by live activity (in+out, busiest first), then trunk type, then
name, under type headers. A card flashes when a health event lands on its group.
Click a card to toggle that group off/on both charts (hidden cards grey out and drop
out of the history totals).
Live chart — 5-minute rolling window
One colour per trunk group; inbound is drawn above the zero line, outbound is mirrored
below it (dashed) — the y-axis shows absolute values and the chart area carries
“↑ INBOUND / ↓ OUTBOUND” zone labels. Shaded zone fills show the org-wide totals behind the
per-trunk lines.
Exactly 60 points (5 minutes at the 5-second poll rate); the window slides continuously.
Current values are labelled at the right edge of each active line; a crosshair tooltip shows
per-trunk in/out at any instant.
↓ PNG exports the chart as an image, annotations included.
Session History — total active calls
Thick Total Inbound (solid, filled) and Total Outbound (dashed) step-lines,
over thin per-trunk background lines. Hidden sidebar groups are excluded from the totals.
Grows from sign-in up to 2,160 points (3 hours at 5 s), then rolls. Mouse-wheel or
pinch to zoom (x-axis), drag to pan; Reset Zoom appears once zoomed.
Long series are LTTB-decimated for render speed without losing peaks. ↓ PNG export.
Health event log
Newest-first log (last 300 entries) of: trunk UP/DOWN transitions (with the group’s
“x/N edges up” context), Genesys notification-channel status changes, browser-WS status, poll
errors, and the sign-in filter note (which inclusion rule applied).
The small source chip flips between poll and ws to show
which feed most recently updated the numbers.
Every UP/DOWN event also drops a vertical annotation line on both charts at the exact
timestamp (the most recent 40 are drawn). Clear empties the log display only.
4Monitoring model
Trunk selection (bootstrap)
At sign-in the app pages through every trunk in the org
(pageSize=100, all pages — orgs with hundreds of trunks are fine) and keeps:
every trunk with trunkType == EXTERNAL;
every PHONE trunk whose name contains one of the terms in the optional phone-trunk
name filter (a deployment setting, case-insensitive) — for organisations that name their
carrier-facing phone trunks consistently; with no filter set, PHONE trunks are not kept;
never an EDGE trunk (inter-edge tie trunks).
If that yields nothing, it falls back to all non-EDGE trunks and flags it — the
filter note in the event log reads “FALLBACK — no trunks matched the standard filter…”.
The kept set is fixed for the session: trunks created after sign-in appear on your next
sign-in.
Two data paths, one truth
REST poll — every 5 seconds —
GET /api/v2/telephony/providers/edges/trunks/metrics with trunkIds as
a single comma-separated value, chunked at ≤ 50 IDs per request (the endpoint rejects
repeated params and caps IDs per call). This is the authoritative time-series: each poll
appends one history point per trunk (the app keeps a 60-point rolling window per trunk and re-sends it with every update, so short gaps in the browser self-heal).
Genesys notifications WebSocket — instant push — one notification channel per
session, subscribed to two topics per trunk:
v2.telephony.providers.edges.trunks.{id} (health: connected state, edge state,
OPTIONS status) and …trunks.{id}.metrics (call counts). Push events update
counters, KPIs and the sidebar between polls, so a trunk going down appears in sub-second time
rather than at the next tick.
Fusion rule: charts add points on poll results only — uniform
5-second spacing, so bursts of pushed events never jitter the time axis. Pushed metric events update the live numbers instantly but wait for the next poll to become chart history. The log’s
source chip shows which feed spoke last.
Alerting — transitions, not thresholds
There are no configurable numeric thresholds. Alerts are the health-topic transitions
Genesys itself pushes: any change to a trunk’s connectedStatus, state or
optionsEnabledStatus becomes a health alert — red/green log entry, chart
annotation, sidebar dot/flash and KPI update, all timestamped at the moment of the event. Poll
results additionally refresh connectedStatus as ground truth every 5 seconds.
Keeping the push feed honest
Heartbeat — the app sends the JSON text frame {"message":"ping"}
every 30 s (Genesys does not use WS ping frames) and expects a pong on
channel.metadata within 10 s, otherwise it terminates the socket.
Reconnect — 10 s after any close the app re-runs the notification setup (fresh channel + subscriptions), never opening duplicate channels. Polling continues throughout, so charts never stop.
Token — the OAuth token is refreshed 60 s before expiry.
5-second poll — single comma-separated value, ≤ 50 IDs per request
POST
/api/v2/notifications/channels
Create the session’s notification channel (one per session / reconnect)
PUT
/api/v2/notifications/channels/{id}/subscriptions
Subscribe 2 topics per trunk: v2.telephony.providers.edges.trunks.{id} (health) + …{id}.metrics (calls)
WS
connectUri (WSS) + {"message":"ping"}/pong
The notification stream itself; JSON heartbeat every 30 s
DEL
/api/v2/notifications/channels/{id}/subscriptions
Teardown — releases the channel quota slot (Genesys returns 405 for DELETE /channels/{id} itself; clearing subscriptions is the supported way)
OAuth client requirements: a Client Credentials grant whose role carries the
Telephony read permission (telephony:plugin:all — Genesys gates the trunk and
trunk-metrics endpoints, and their notification topics, behind this single permission). The
notification-channel endpoints themselves need no extra permission — any authenticated client may
manage its own channels, subject to the ~20-channels-per-client quota.
Data caveat (BYOC Cloud):…/trunks/metrics returns rows only
for edge-registered, reachable trunks. BYOC Cloud trunks and fully offline trunks return no
metric rows — health may still arrive via notifications. The app logs
“0 metric entries — trunks may be BYOC Cloud or all offline” when a whole poll comes back
empty; it is a platform characteristic, not a fault in the monitor.
Channel hygiene: every teardown path — Disconnect, tab close, inactivity, service shutdown — clears the channel’s subscriptions so the org’s quota slot is reclaimed;
Genesys also expires idle channels after ~24 h. If you ever hit channel-quota errors, they
normally come from other tools sharing the same OAuth client — give Trunk Monitor its own
client.
6Storage, privacy & security
Nothing is stored. There is no database: sessions, trunk snapshots and chart history exist only while you are signed in and vanish on sign-out or a service restart.
Credentials — client ID/secret are held on the server for the lifetime of your session (the poller needs them to refresh the OAuth token) and are never written to storage, never logged, and never sent to the browser — the dashboard only ever sees the first 8 characters of the client ID. The secret exists in the browser only inside the login form while you type it.
Sessions — protected by a secure session cookie; sessions end after a period of inactivity.
Browser storage — your browser remembers only the last-used client ID + region. Never the secret.
Session isolation — every request is checked against your own session; the support diagnostic view only ever reveals your session.
External fetches from the browser — the charting components and UI fonts load from public providers; no org data is ever sent there, but the dashboard needs internet access to render charts (§8).
7Technology
Web application — one session per signed-in user bridges two live feeds — the 5-second metrics poll and the Genesys notifications stream — onto one live connection to your browser.
Browser interface — a single-page live dashboard with zoomable, annotated charts and a dark theme.
State — no database. Chart history lives in the session (and the browser) only. One cleanup path is shared by tab close, Disconnect, sign-out and inactivity: end the session, stop the poller, close the Genesys connection and clear the channel subscriptions, so the org’s channel-quota slot is always released.
8Troubleshooting
Sign-in fails / returned to the sign-in page with an error.
The error text is the Genesys message. Check the region (the token must be minted in the org’s home region), the credentials, and that the OAuth client’s role has the Telephony read permission (§5). A 401 means bad credentials; a 5xx means Genesys or network trouble.
“The service is busy – try again shortly.”
The service is handling as many sign-ins as it can. Re-signing in with the same client ID + region replaces your own earlier session automatically; otherwise try again shortly.
I refreshed the page and landed on the login screen.
By design: the reload closes the dashboard’s live connection, and closing it tears the whole session down (that is what guarantees the Genesys channel quota is always released). Region and client ID are pre-filled — re-enter the secret.
All trunks show 0 calls; log warns “0 metric entries — trunks may be BYOC Cloud or all offline”.
The metrics endpoint only returns rows for edge-registered, reachable trunks. BYOC Cloud trunks and fully offline trunks yield none — health can still arrive via notifications. A Genesys data characteristic, not a monitor fault.
The WS chip says “WS Closed” and I end up on the login page.
Your session has ended — after a period of inactivity, or because the service was restarted. Repeated failed reconnects have the same effect. Sign in again.
Event log shows “Genesys WS — Disconnected, reconnecting…” now and then.
The Genesys-side socket dropped (Genesys recycles sockets periodically; a missed pong forces a close after 10 s). The app reconnects with a fresh channel after 10 s; polling never stops, so charts continue seamlessly. If it flaps continuously, contact QVCCS support.
A trunk I expect isn’t listed.
Check its type: only EXTERNAL trunks and PHONE trunks matching the phone-trunk name filter are kept; EDGE ties never are. The event log’s filter note says which rule applied. Trunks created after sign-in appear on your next sign-in — the set is fixed at sign-in.
Charts are blank but the counters move.
The charting components and fonts load from the internet — on a network without internet access the data still flows but charts cannot render. The live chart also shows “Waiting for first poll…” until the first 5-second tick lands.
Two tabs open — one went quiet.
A session has exactly one live browser connection; the newest tab takes the feed. Closing either tab ends the session for both. Use one tab per sign-in (or a second OAuth client for a second screen).
Gaps in the history chart after my laptop slept.
Browsers throttle background tabs, and a suspended machine closes the live connection (→ session cleanup, see the refresh entry above). After re-login the rolling window refills within a few polls; the app re-sends its 60-point window with every update, so short gaps self-heal.
Is anything kept between restarts?
No. Sessions, snapshots and history exist only while you are signed in. A service restart signs everyone out (“Server shutting down”) and starts everyone’s history fresh at next sign-in.
QVCCS Trunk Monitor — real-time external-trunk health and call-volume monitoring for Genesys Cloud CX. Strictly read-only against the Genesys APIs; nothing stored, no database.
Continuously integrated and updated. This is a published sample of the user guide. The App Suite changes frequently, so this page may not reflect the latest features, screens and behaviour. The current guide is available in the application through the QVCCS apps portal, included with every Managed Professional Services tier.
Included at every tier
Use Trunk Monitor with QVCCS Managed Professional Services.
The App Suite comes with every Bronze, Silver, Gold and Diamond subscription, used by our engineers and your administrators alike – backed by the certified QVCCS bench.