QVCCS App Suite · Audit, compliance & governance

Config Validator

A read-only as-built reviewer for a Genesys Cloud CX organisation. One click traverses nine REST endpoint families — users, stations, phones, sites, phone base settings, queues and groups with full member lists — joins everything into one row per user, and streams the run live with a terminal-style API log. The finished report is a 13-column table you can search, filter eight ways, sort and export to CSV, Excel or PDF, entirely in the browser.

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

  • as-built configuration report
  • one row per user
  • multi-user
  • adaptive rate pacing
  • live API log
  • csv · xlsx · pdf
  • strictly read-only

Security at a glance

Config Validator

Read-only

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; report data lives only in your browser tab and is gone on refresh
AI
No AI
Exports
CSV, Excel and PDF of the filtered rows
Genesys Cloud permissions
View on Users, Authorization, Telephony, Routing and Groups; optional organization:readonly

Compare every app

1What it is

The As-Built Configuration Validator answers a question the standard Genesys Cloud admin UI makes difficult: “For every user in my org, what phone do they have, is it allocated and set as their default station, what queues are they in, which groups do they belong to, and what roles have they been assigned?”

One click runs a full traversal of the org’s configuration. The app pages through users, stations, phones, sites, phone base settings, queues (with member lists) and groups (with member lists), joins everything into one row per user, and streams progress live to the browser. Once the report lands, everything else — search, eight filters, sorting, three export formats — happens instantly in the browser with no further API traffic.

Typical use cases

  • Go-live / as-built validation — verify every agent has a phone that is both allocated and configured as their default station (the “✓ Allocated + Default” provisioning filter is the health check this app was built around).
  • Audit & handover documentation — export the full user/telephony matrix to XLSX or a landscape PDF.
  • Role / queue / group reviews — filter by a specific role, queue or group and see exactly who holds it, including on deactivated accounts.
  • Contact-data hygiene — the Profile Contacts column shows every address on the user record (login email, work/home/mobile phones, extra emails, SMS) with the primary entries starred.
Read-only by design. The application only ever issues GET requests against the Genesys API, plus the one POST /oauth/token needed to sign in. Nothing in your organisation is modified, and no report data is stored by the app — it lives only in your browser tab and disappears on refresh.

2Quick start

  1. Create an OAuth client in Genesys Cloud (Menu > IT and Integrations > OAuth), grant type Client Credentials, with read-only permissions for Users, Authorization, Telephony, Routing and Groups (see §6). Note the Client ID and Secret.
  2. Sign in — open the app, pick your region (14 supported), paste Client ID and Client Secret, press Sign in. Credentials are validated with one real OAuth call and held on the server; they are never sent to the browser.
  3. Run the report — press ▶ Run Report (or just Enter). Watch the progress bar and the API Communications Log. Small orgs take seconds; large orgs several minutes, because calls are deliberately paced under Genesys rate limits.
  4. Filter and export — combine the free-text search with the State / Phone / Role / Queue / Group / Site / Phone Status / Provisioning filters, then export the filtered rows to CSV, XLSX or PDF.
Sessions: several users can be signed in at once, each with their own credentials and their own adaptive rate pacer. Sessions end after a period of inactivity; signing in again with the same Client ID + region reclaims your earlier session.

3UI walkthrough

Sign-in page

A split-screen page: a royal-blue brand rail on the left (hidden below 1024 px) and the form on the right. The form fields, in order:

  • Region — a dropdown of the 14 Genesys regions ( Mumbai, Seoul, Sydney, Tokyo, Canada Central, Frankfurt, Ireland, London, Zurich, UAE, São Paulo, US East Virginia, US East 2 FedRAMP, US West Oregon).
  • Client ID and Client Secret of the OAuth Client Credentials grant.

On failure you return to the sign-in page and the exact Genesys error message renders in a red box. As a convenience the page remembers your Client ID and region in your browser and pre-fills them next time; the secret is never stored.

Dashboard & report run

  • Header — the “GC” mark and app title on the left; a centred organisation banner (resolved via /api/v2/organizations/me at sign-in — it stays an italic “—” if the OAuth client lacks the permission); region label and “Generated” timestamp on the right after a run.
  • Run Report card — a session indicator (“Signed in”), the ▶ Run Report button (disabled and showing “⏳ Running…” while a run is live), 📖 Guide (opens this manual in a new tab) and Sign out. Pressing Enter anywhere also starts a run.
  • Progress panel — spinner, stage message and a 0–100% bar driven by live progress (users → stations → phones → sites → base settings → queues → groups → mapping).
  • API Communications Log — a terminal-style panel that opens (and auto-clears) at the start of every run. Each log entry renders as a timestamped line with a colour-coded tag: INFO, SUCCESS (green), FETCH (violet), API (blue, one line per page fetched with running totals), WARN (amber — member-fetch failures, pacing changes) and ERROR (red). Clear and Hide/Show buttons sit in its header; the panel persists after completion so the full API trace can be reviewed next to the data.
  • Error banner — fatal errors render here. If the live connection is lost (typically an ended session or a service restart) the banner shows “Connection to server lost — returning to sign-in…” and the page returns to the sign-in page.
  • Stats bar — six chips with the raw totals loaded: Users, Stations, Phones, Sites, Queues, Groups (unaffected by filters). A result counter on the toolbar’s right shows filtered / total users.

The result table (13 columns)

Sticky header, zebra striping, and a 1500 px minimum width with horizontal scrolling on narrow viewports. Nine columns sort on click (↑/↓ indicator); the default sort is Name A→Z.

ColumnSortableContent
Nameyes (last name)Full name with department/title beneath in small type.
EmailyesLogin email, mono, ellipsised — hover for the full value.
StatusyesUser state badge: active (green) / inactive (amber) / deleted (red).
Profile Contacts—One row per contact entry: a ★ that lights green on primary entries, the value (emails violet, SMS amber, phones grey), an extension tag (x1234) and a type tag (Work, Work 2–4, Home, Mobile, Main, Other, SMS, Work Email…).
Default PhoneyesThe contact entry flagged primary for voice, in green.
Roles / Queues / Groups—Colour-coded pills (roles blue, queues blue, groups violet); first 3 shown, then a “+N” chip whose hover tooltip lists the rest.
Assigned PhoneyesResolved phone name; WebRTC softphones get a “WebRTC” badge.
Phone TypeyesPhone base settings name (e.g. WebRTC Phone, AudioCodes …).
SiteyesTelephony site of the phone (station-site fallback).
Phone StatusyesBadge: operational / active (green), degraded / inactive (amber), failed / error (red), deleted, unknown.
Allocated / Default StnyesTwo stacked badges: “✓ allocated” vs “✗ not alloc”, and “★ default stn” vs “not default”.

Search & filters (combinable, instant, client-side)

  • Free-text search — matches name, email, department, title, every contact string (including its [mediaType]/[subType]/[primary] tags, so “mobile” or “primary” work as searches), role names, phone name/type/site and station name. Queue and group names are not in the search index — use their dropdowns.
  • State — Active / Inactive / Deleted.
  • Phone presence — Has Phone / No Phone / Phone Allocated / Phone Unallocated.
  • Role, Queue, Group, Site — dropdowns populated from the loaded data itself.
  • Phone Status — logical buckets over the raw status: Operational/Active, Degraded/Inactive, Failed/Error, Deleted, Unknown, and “— No Phone”.
  • Provisioning — the go-live health check: ✓ Allocated + Default (good), ⚠ Allocated, not Default, ✗ Phone, not Allocated, — No Phone at all (§4).

Exports (respect current filters)

All three exports contain exactly the filtered rows at the moment you click, are generated entirely in the browser, and silently do nothing when the filtered set is empty.

ExportFileNotes
CSVabcv-report-YYYY-MM-DD.csv20 columns: First/Last Name, Email, Department, Title, State, Profile Contacts, Default Phone, Roles, Queues, Groups, Station Name/Type, Phone Name, WebRTC Phone, Phone Type, Site, Phone Status, Allocated, Default Station. Multi-value fields joined with “ | ”.
XLSabcv-report-YYYY-MM-DD.xlsxSame 20 columns with sized column widths.
PDFabcv-report-YYYY-MM-DD.pdfLandscape A4, condensed 15-column layout, footer with timestamp + page numbers.
Internet dependency: the export components and webfonts load from public providers when the dashboard page loads. If the browser had no internet access at that moment, the export buttons cannot work until the page is reloaded with connectivity. Report data itself is never sent to them.

4Domain concepts

The user → station → phone chain

Connecting a Genesys user to a phone requires traversing three object types. The validator resolves the chain through three paths, in order:

  1. WebRTC path — station.webRtcUserId links station → user, and phone.lines[0].id === station.id links phone → station. The most reliable path for WebRTC softphones.
  2. User-station path — user.station.associatedStation.id (the currently logged-in station) or user.station.defaultStation.id (the permanently configured one), resolved through a phone-by-station index (physical phones link via phone.station.id).
  3. Fallback — any station whose associatedUser / defaultUser matches the user.

Allocated vs. default station

  • Allocated (“✓ allocated”) — a Genesys phone record was successfully resolved for the user’s station. Unallocated means a station exists but no phone record maps to it.
  • Default station (“★ default stn”) — the resolved station’s id equals user.station.defaultStation.id, i.e. the assignment is permanent configuration, not just a transient login association. An agent who is allocated but not default will lose their phone at next logout — which is exactly what the “⚠ Allocated, not Default” provisioning filter surfaces.
  • WebRTC badge — shown when the station’s type contains webrtc (e.g. inin_webrtc_softphone).

Profile contacts and the primary star

The Profile Contacts column merges three sources from the user record, in order: the login email (user.email / username — what Genesys shows as “Main Email”), every entry in addresses[] (work/home/mobile/main/other phones, extra emails, SMS numbers, extensions), and any primaryContactInfo[] entries not already captured. Primary detection compares normalised values — phone formatting is stripped to digits, emails lowercased — so “(+1 202-555-0143)” and “+12025550143” match. Deduplication mirrors the Genesys UI: phones dedupe on the normalised number, emails dedupe case-sensitively (the same email in different case shows twice, as Genesys does).

Phone status semantics

The status badge prefers the edge-reported operational status (phone.status.edges[0].status: Operational, Degraded, Failed…). When the edge reports “Unknown” or nothing, the phone’s administrative state is used instead (active → Active, inactive → Inactive, deleted → Deleted), and only then does it fall back to “Unknown”. The Phone Status filter groups these into buckets: Operational+Active, Degraded+Inactive, Failed+Error, Deleted, Unknown, plus a synthetic “— No Phone” bucket.

Provisioning states

Filter valueMeaningAction usually needed
✓ Allocated + DefaultPhone resolved, allocated, and the station is the user’s configured defaultNone — correctly provisioned
⚠ Allocated, not DefaultPhone works now but is only a transient associationSet the station as the user’s default station
✗ Phone, not AllocatedA phone record exists but is not marked allocated to the userFix the phone/station assignment
— No Phone at allNo phone record resolved by any pathProvision a phone/station
Why deleted and inactive users appear: users are fetched with state=any on purpose, so as-built reviews catch lingering queue/group/role assignments on deactivated accounts. Use the State filter to hide them.

5Report pipeline & resilience

The eight stages

A report run is one long-lived live connection. The app works through the stages below, reporting progress and log lines throughout, then sends the entire joined result in one go when it completes:

#StageNotes
1Usersexpand=authorization,station&state=any — roles and station links ride along; all user states included
2StationsFull station inventory
3Phonesexpand=status — edge-reported operational status included
4SitesSite id → name map
5Phone base settingsOne GET per unique id, fired in batches of 10 — resolves the “Phone Type” column
6Queues + membersQueue list, then per-queue member lists 8-wide with a 90 s per-queue cap
7Groups + membersGroup list, then per-group member lists only 2-wide (tight Genesys rate bucket), 90 s cap, per-page log lines
8JoinLookup maps built; one row assembled per user; totals reported

All list endpoints request pageSize=200 (the Genesys maximum) to halve round-trips.

Adaptive per-session pacer

Every Genesys call in a session flows through a pacer that enforces a minimum spacing between calls — even parallel fetchers serialise through it, so the on-wire rate stays steady regardless of concurrency:

  • Baseline 250 ms spacing (≈4 req/s, under Genesys’ standard 5 req/s); floor 200 ms.
  • On each HTTP 429 spacing multiplies ×1.5, capped at 2000 ms (0.5 req/s emergency floor). The log shows “⚠ Rate limit hit — slowing to N req/s”.
  • Relaxation — after 30 consecutive non-429 responses, spacing eases ×0.85 back toward the baseline (“✓ Sustained success — easing pace”), so one brief throttle doesn’t slow the whole run.

Retry & token policy

  • 429 / 503 — up to 3 attempts, honouring Retry-After (default 5 s) plus up to 40% random jitter, capped at 60 s per wait, and each 429 also adapts the pacer so subsequent calls don’t burst straight back into the limit.
  • 401 mid-run — exactly one token refresh + one retry. Refreshes are concurrency-guarded: parallel fetchers that hit expiry simultaneously all await the same OAuth call.
  • Proactive refresh — tokens are treated as expired 60 s early and refreshed before a call fires. Each request times out after 30 s.
  • Membership timeouts — each queue/group member fetch is capped at 90 s so one hung (typically dynamic-membership) group can’t stall the stream; failures are logged as warnings and the report still completes.
Why groups run only 2-wide: Genesys applies independent rate-limit buckets per endpoint family, and /api/v2/groups/{id}/members has a much tighter bucket than queue members — 9 parallel calls reliably triggered 429s with a 60-second Retry-After. Two concurrent fetches stay under the threshold while still overlapping slow groups.

6Genesys endpoints & permissions

EndpointOptionsUsed for
POSTlogin.<region>/oauth/tokenclient_credentialsSign-in and mid-run token refresh
GET/api/v2/organizations/mebest-effort at sign-inOrg display name for the header banner
GET/api/v2/usersexpand=authorization,station&state=anyUsers incl. roles + station links, all states
GET/api/v2/stations—Station inventory
GET/api/v2/telephony/providers/edges/phonesexpand=statusPhones incl. edge status
GET/api/v2/telephony/providers/edges/sites—Site id → name map
GET…/edges/phonebasesettings/{id}batches of 10Phone-type names
GET/api/v2/routing/queues · …/queues/{id}/membersmembers 8-wide, 90 s capQueue membership per user
GET/api/v2/groups · …/groups/{id}/membersmembers 2-wide, 90 s capGroup membership per user

OAuth client permissions

Assign a role to the Client Credentials grant covering these read-only permission areas:

Permission areaLevelUsed for
Users (directory)ViewUser profiles, names, emails, states, contact addresses
AuthorizationViewRole assignments via expand=authorization
TelephonyViewPhones, stations, sites, phone base settings
RoutingViewQueues and queue member lists
GroupsViewGroups and group member lists
Organization (organization:readonly)View — optionalOrg name banner only; sign-in and reports work without it
Read-only posture: apart from the OAuth token request, every Genesys call the app makes is a GET. Missing a permission never breaks the whole run — the affected fetches fail, are logged as warnings, and the corresponding columns simply come back empty.

7Storage, privacy & security

  • Nothing persists. No database and nothing written to storage. Report data exists only in the browser tab; sessions exist only while you are signed in and end if the service is restarted.
  • Credentials stay on the server. The Client Secret is held on the server for the session’s lifetime only and is never sent to the browser, which holds only a secure session cookie. Credentials never appear in web addresses, browser history or referrer headers.
  • Login hint only. The login page remembers Client ID + region in your browser as a convenience; the secret is never stored in the browser.
  • Session lifecycle. Sessions end after a period of inactivity, discarding their credentials; a repeat sign-in with the same Client ID + region reclaims your earlier session. Sign out ends the session immediately.
  • Gated pages. The dashboard and report require a signed-in session; only the sign-in page and this guide are public.
  • Outbound traffic. The app talks only to your org’s Genesys region. Your browser loads export components and webfonts from public providers at page load; report data is never sent to any third party.

8Technology

  • Web application — the adaptive per-session pacer, a resilient read-only Genesys client (30 s per-request timeout, retry and pacing) and the live report engine. No database.
  • Browser interface — a sign-in page and a dashboard that receives the live report and does all table rendering, searching, filtering, sorting and exporting in your browser.
  • Streaming — progress, the API log and the finished report all arrive over one live connection.
  • Persistence — none: sessions exist only while you are signed in, report data only in the browser tab.

9Troubleshooting

“The service is busy – try again shortly” on sign-in.
The service is handling as many sign-ins as it can. If you already hold a session (an orphaned tab), sign in again with the same Client ID and region — your earlier session is reused instead of rejecting you. Otherwise try again shortly or ask another user to sign out.
Login fails with an OAuth error.
The message on the login page comes straight from Genesys. Typical causes: wrong region selected for the org, a regenerated Client Secret, or the OAuth client is not a Client Credentials grant. Check Menu > IT and Integrations > OAuth.
The run slows mid-way (“⚠ Rate limit hit — slowing to N req/s”).
Genesys returned HTTP 429. Expected behaviour, not a fault: the adaptive pacer multiplies the gap between calls ×1.5 per throttle (floor 0.5 req/s) and eases back after 30 consecutive successes. The run continues; it just takes longer. Note that concurrent runs by several signed-in users share the same org-side rate limits.
“Connection to server lost — returning to sign-in…”
The live connection ended — usually a session that ended after a period of inactivity, or a service restart. The page returns to the sign-in page; sign in again.
Phone Type shows “—” for some phones.
Those phones’ base-settings lookups failed — the log line “⚠ Phone base settings: X/Y loaded · N failed” counts them. Usually transient throttling: re-run the report. It can also mean the OAuth client lacks telephony read permission on those objects.
“⚠ Queue/Group … member fetch failed” warnings in the log.
Individual membership lookups can time out (90 s cap on a huge dynamic group) or exhaust their 3 retries under throttling. The report still completes; affected users simply won’t show that queue/group. Re-running usually fills the gaps — the group lane is intentionally only 2-wide because Genesys’ /groups/{id}/members bucket answers bursts with 60-second Retry-After penalties.
The organisation banner stays “—”.
The OAuth client lacks permission for GET /api/v2/organizations/me (organization:readonly). Sign-in and reports work regardless; only the banner is blank.
Users show no queues at all, but roles look right.
Roles arrive on the user objects (expand=authorization), but queue membership needs /api/v2/routing/queues/{id}/members. If the client lacks routing read permission every queue’s member fetch fails (see the log warnings). Grant routing View and re-run.
Export buttons do nothing.
Two possibilities: the filtered row set is empty (exports are a deliberate no-op), or the export libraries never loaded because the browser had no internet access when the page loaded — reload with connectivity and re-run the report.
A search for a queue or group name returns nothing.
By design queue/group names are not in the free-text index — use the Queues / Groups dropdowns (they are populated from your org’s actual data after the run) and combine with search as needed.
The progress bar briefly steps backwards near the end.
Cosmetic: the “Mapping data…” stage reports a lower percentage than the membership stages that precede it. The run is fine — the finished report follows moments later.
Why do deleted/inactive users appear?
Users are fetched with state=any on purpose so reviews catch lingering assignments on deactivated accounts. Use the State filter to hide them.
Is anything written to my org or stored on the server?
No writes ever occur (GET-only traversal, plus the OAuth token POST). Credentials are held only on the server for your session’s lifetime; report data exists only in your browser tab and disappears on refresh.

QVCCS Config Validator — as-built configuration validation for Genesys Cloud CX. Strictly read-only against the Genesys APIs; nothing stored — report data lives only in your browser tab.

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 Config Validator 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.

Explore the tiers

Last reviewed

Questions about what you have read?

Clients, partners and people introduced to us can reach the specialists behind our applications and articles directly.

Who to contact