A read-only Genesys Cloud audit that maps every inbound DID and trunk number to the
Architect flow it lands on, then cross-checks those numbers against agent profile numbers, duplicate
flow routings and outbound campaign caller-IDs. Stale, orphaned and dual-routed numbers surface
without trawling a spreadsheet. Appears in-app as QVCCS DID Validator.
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
DID → flow audit
multi-user
no results stored
live scan log
csv · xlsx · pdf export
strictly read-only
Security at a glance
DID Conflict Checker
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; audit results live only in the browser tab that ran the audit
AI
No AI features are described in the user guide
Exports
CSV, Excel and PDF, built in your browser
Genesys Cloud permissions
Read-only telephony (DIDs, pools, sites, trunks), architect (flows, IVRs), routing and user directory; optional outbound:readonly, organization:readonly
DID Conflict Checker answers four questions that are painful to answer from the Genesys Cloud
admin UI:
Where does every number go? — Every DID, DID-pool boundary, site number-plan entry and
trunk inbound route is mapped to the Architect inbound flow it ultimately reaches, with a
clickable deep-link into Architect.
Does any agent’s profile number collide with a flow DID? — An agent whose Work/Mobile
number equals (or ends with the same 10 digits as) an inbound DID will produce baffling routing
behaviour; every collision is listed per agent with the exact profile field at fault.
Is any number routed to more than one flow? — “Duplicate routings” are dead routes:
Genesys uses the first match and the other assignments silently never fire.
Is any inbound DID also an outbound campaign caller-ID? — The “ghost ring” hazard: a
customer dials your number and their phone then rings showing their own number.
A single Run Audit click walks the org (inbound flows → Architect IVRs → four DID sources →
active users → outbound campaigns), streams progress into a live scan log, and renders a
results workspace: routing-source analysis with an ownerType census, per-flow number chips with
country flags, duplicate-routing and ghost-ring banners, agent conflict cards, and CSV / Excel / PDF
exports. An optional second pass inventories every non-voice flow type (chat, email, SMS, secure
call, bot, workflow, in-queue, outbound, survey) for a complete Architect catalogue.
Read-only by design. Only GET requests are made against your org
(plus the OAuth token call). Nothing is modified, and results are never stored server-side — they
live in your browser tab until you run the next audit.
2Quick start
Sign in — open the app; you land on the sign-in page. Pick the
Region (the canonical 14-region list), then enter the Client ID and
Client Secret of an OAuth client-credentials grant with read-only telephony,
architect and routing access (§5). The app validates the pair with one real OAuth call and signs you in — the secret is held on the server and never sent back to the browser.
Run Audit — one click in the sidebar. The Scan Log fills stage by stage
(auth → flows → IVRs → sources A–D → users → cross-reference → outbound); most orgs complete in
well under a minute.
Read the results — the status chip flips to All clear or N conflict(s);
cards render top-to-bottom: source analysis, flows & numbers, agent conflicts. Red 🚨 and
amber ⚠ banners are the findings; everything else is inventory.
Drill down — filter flows by name or number, click a flow name to open it in Architect,
click a flow UUID to copy it.
Export — CSV, Excel or a branded PDF from the header. Exports honour the on-screen flow
filter.
No writes, no state: re-running is always safe and always fresh. There is
no cache to clear and no database to maintain — each audit re-reads the org.
3UI walkthrough
Sign-in page
Region dropdown (14 Genesys regions, flag-labelled), Client ID, Client Secret. On success you go straight to the workspace; on failure the page shows the exact Genesys error.
The browser remembers the Client ID and region only as a convenience hint. The secret is never stored in the browser.
The left rail summarises the product; the guide (this page) is linked from the workspace and is
readable without signing in.
Header & sidebar
Header — brand block; a centred org name + region banner that appears after the
first audit (long name from /api/v2/organizations/me, with
thirdPartyOrgName shown when it differs); the Export group (CSV / Excel /
PDF, revealed once results exist); and a live status chip
(Ready → Scanning… → All clear / N conflict(s) / Error / Disconnected).
Signed in panel — shows the authenticated region; the credentials themselves stay on the server.
Run Audit — starts a run; disabled while one is streaming.
📖 Guide — opens this manual in a new tab. Sign out stops any active scan, ends your session and returns to the sign-in page.
Scan Log — every pipeline stage streams here with ✓ (done) / ✕ (failed) / › (running)
markers, including per-page pagination progress on large orgs.
Results panel — Flows, DIDs, Mapped, Agents and Conflicts counters, pinned to the
sidebar bottom.
Routing Source Analysis card
A table of the five routing data sources — IVR (Architect IVR configs) and
A DID records / B DID pools / C site number plans / D trunk inbound
routes — each with its mapped count and the exact Genesys endpoint behind it, plus a U row
for the harvested users (not a routing source; shown because supervisors asked how many profiles
were inspected).
ownerType breakdown — a census of every DID record’s ownerType
(IVR_CONFIG, USER, UNKNOWN, …). This is the fastest
explanation of “why did nothing map” — e.g. every DID owned by USER means there are
no flow assignments to find.
A zero-mapped warning banner appears when no source produced a mapping, with the remediation
hint (assign numbers to IVR configurations in Architect).
Outbound caller-ID banner — every inbound DID that is also a campaign
callerAddress, E.164-sorted with country flag, the inbound flow, the campaign name
and an Active/Off pill (Active = campaign status on or
on_complete).
Inbound Flows & Assigned Numbers card
Duplicate-routing banner — up to 20 dual-routed numbers listed inline (E.164-sorted;
the remainder are in the exports), each showing every flow the number is registered to with its
source provenance.
Filter toolbar:
Hide flows containing… — reverse name filter (type staging to hide
every staging flow).
Find by number… — digits-only partial DID search across each flow’s numbers.
Sort — name A→Z (default), flow type, most DIDs first, no DIDs first, oldest
published first, newest published first.
⊘ Only flows with no DID — orphan-flow toggle.
The counter pill switches to “N shown · M hidden · T total” while any filter is active.
Per-flow row — the flow name is an Architect deep-link
(https://apps.<region>/architect/#/<type>/flows/<id>/latest);
chips show flow type (only when the set is mixed-type, with a per-type glyph), division,
staleness (⏰ Nd when last published ≥ 180 days ago) and 🚨 duplicate count; the flow UUID
is click-to-copy.
DID chips — numbers sorted by E.164 and rendered with a country flag + national digit
grouping (e.g. 🇬🇧 +44 1134 960123) plus a source pill (DID, DID Pool,
Site: name, Trunk: name, or the IVR name). Flows with no numbers show
“Unassigned”.
Non-voice flow inventory (two-stage discovery)
The headline audit is voice-only by design — DIDs, pools, number plans and trunk routes
are voice concepts. After it completes, the “Also list non-voice flows” button backfills
the other 11 flow types: INBOUNDCHAT, INBOUNDEMAIL,
INBOUNDSHORTMESSAGE, SECURECALL, WORKFLOW,
BOT, INQUEUECALL, INQUEUEEMAIL,
INQUEUESHORTMESSAGE, OUTBOUNDCALL, SURVEYINVITE — fetched
in parallel.
The card offers a name filter, per-type toggle pills (all present types on by default),
the same sort selector, division/staleness chips and Architect links. DID chips are deliberately
absent — these types cannot carry DIDs. The button collapses to Reload inventory.
Types that could not be fetched (usually a missing scope) are flagged:
“⚠ Could not fetch: … — likely missing OAuth scope.”
Agent Conflict Check & Conflict Summary
Either an All clear state, or one card per flagged agent showing name / email / user id
and, per conflict: the profile field at fault (e.g. addresses › WORK), the
agent number, and the conflicting DID with its flow.
When conflicts exist, a flat Conflict Summary table repeats every conflict row
(agent · email · field · number · DID · flow) for easy copy/paste into a ticket.
Exports
All three exports run entirely in the browser and honour the current flow filter for the
flow↔DID listing (conflicts, duplicates and outbound conflicts always export in full — they are a
separate concern). When a filter is active, filenames carry a
_FILTERED_… tag naming it (e.g. _FILTERED_exclude-staging_nodid).
Export
Contents
CSV
Four files, downloaded in sequence: QVCCS_FlowDIDs…
(flow → number rows, E.164-sorted, with country ISO + source), QVCCS_Conflicts…,
QVCCS_DuplicateRoutings…, QVCCS_OutboundCallerIDConflicts…
Excel
One workbook, five sheets: Flow DID Mapping · Agent
Conflicts · Duplicate Routings · Outbound Caller-ID · Summary (stats + ownerType census). Org
name and filter are stamped on the header rows
PDF
Branded landscape-A4 report: executive summary with
stat boxes and source table, flows & numbers, duplicate routings (if any), outbound
caller-ID conflicts (if any), agent conflict report, page numbers — suitable for audit
hand-over
Connectivity caveat: the Excel and PDF export components load from the internet when the page loads, so Excel/PDF need the browser to have internet access at that moment — see §8. CSV needs nothing extra.
4Domain concepts
IVR configs — the canonical DID→flow bridge
In Genesys Cloud, phone numbers are normally assigned to Architect IVR configurations
(Admin → Architect → IVRs), and each IVR points at flows. DID Conflict Checker fetches all IVRs first and
builds ivrId → flow from the first of openHoursFlow / flow /
defaultFlow / closedHoursFlow / holidayFlow, then registers
every number in the IVR’s dnis[] against that flow. DID records whose
ownerType is IVR_CONFIG resolve through the same map.
The four DID sources (A–D)
A — Individual DID records — three-pass resolution: (1) ownerType=IVR_CONFIG
via the IVR map; (2) owner.id is directly an inbound-flow UUID; (3) type-hinted
(ownerType=FLOW, or a selfUri containing /flows/).
Unmatched numbers are kept as “Unassigned (ownerType)” so they still participate in the
agent conflict check.
B — DID pools — the pool’s start/end boundary numbers are
registered (interior numbers are implied); the flow row displays the range as
start → end.
C — Site number plans — every telephony site’s /numberplans is fetched;
sites answering 403/404/405 are skipped silently. Plans resolve at plan level and again per
number entry (an entry can carry its own flow ref).
D — Trunks — inbound routing embedded on the trunk
(numberPlans / inboundRoutes / numberMaps); only trunks
with embedded routing contribute.
Across all sources, a records-agnostic fallback resolver tries owner/ownerType, routingTarget,
flow/inboundFlow/destinationFlow, inboundRoute,
callRoute, flowId, and destination/target —
covering GCV standard, BYOC and legacy field shapes.
Number normalisation & the conflict rule
Numbers are stripped to digits (keeping a leading +). Two numbers conflict
when they are equal or when their last 10 digits match — so
+1 202-555-0143 and 12025550143 collide as intended. Numbers shorter than
10 digits (extensions) only match exactly. Agent numbers are harvested from
addresses[], primaryContactInfo[] (phone-ish media types) and
phones[] of active users, de-duplicated, and compared against every
registered number — mapped or unassigned.
Duplicate routings vs provenance overlap
Every registration is kept per number. A number registered to two or more distinct flows
is a duplicate routing — Genesys uses the first match; the other assignments are dead configuration.
Two registrations of the same number to the same flow from different sources (an IVR config
and a DID record both pointing at one flow) are not duplicates — that is provenance overlap
and expected. The first-registered flow also “owns” the number for the conflict check.
Ghost ring (outbound caller-ID conflict)
A number that is both an inbound DID and an outbound campaign caller-ID
(callerAddress) produces the ghost-ring experience: a customer dials your number, and
moments later their phone rings displaying their own number. The audit cross-references the
full inbound set against all outbound campaigns and flags each collision with the campaign’s active
state. Campaigns inheriting caller-ID from the contact list have no callerAddress and
cannot be checked this way.
Staleness
A flow is marked stale (⏰ chip) when its last publish —
publishedVersion.dateCreated, falling back to checkedInVersion.dateCreated,
then dateModified — is ≥ 180 days ago. Combined with the ⊘ no-DID toggle this is
the decommission-candidate finder.
Number presentation
Raw E.164 values are resolved against a longest-prefix country table covering every region
Genesys is commonly deployed in (NANP islands before the +1 catch-all), then spaced per
that country’s national grouping and prefixed with a flag emoji. Sorting is always by underlying
E.164, so +44… blocks stay contiguous.
The audit pipeline (what Run Audit actually does)
OAuth token — POST login.<region>/oauth/token
Org name (best-effort) — GET /api/v2/organizations/me
Inbound flows — GET /api/v2/flows?type=INBOUNDCALL&deleted=false → flow map
Architect IVRs — GET /api/v2/architect/ivrs → dnis[] registered to
each IVR’s flow
Source A — DID records (three-pass resolution, ownerType census, unmatched kept as
unassigned)
Source B — DID pools (start/end boundaries)
Source C — sites → per-site number plans
Source D — trunks (embedded inbound routing)
Users — GET /api/v2/users?expand=addresses,primaryContactInfo&state=active
Agent conflict check — last-10-digit comparison of every agent number vs every registered
number
Duplicate routings — any number registered to >1 distinct flow
Outbound caller-IDs — GET /api/v2/outbound/campaigns vs the inbound DID set
Results — everything is sent to your browser in one go and the run finishes
5Genesys endpoints & permissions
Everything below is paginated at 100 items/page where applicable and called with a fresh
client-credentials token per audit run.
Endpoint
Used for
POST
login.<region>/oauth/token
Client-credentials sign-in validation + one fresh token per audit run
GET
/api/v2/organizations/me
Org long name + thirdPartyOrgName for the header banner (best-effort; failure only blanks the banner)
GET
/api/v2/flows?type=INBOUNDCALL&deleted=false
The inbound-flow universe (name, type, division, publish/modify dates)
GET
/api/v2/architect/ivrs
The canonical DID→flow bridge: dnis[] + open/closed/holiday flow refs
GET
/api/v2/telephony/providers/edges/dids
Source A — individual DID records (ownerType census kept)
Agent profile numbers for the conflict cross-reference (active users only)
GET
/api/v2/outbound/campaigns
Ghost-ring check — optional; skipped gracefully without outbound read access
GET
/api/v2/flows?type=<T>&deleted=false ×11
Non-voice inventory — only when “Also list non-voice flows” is clicked
OAuth client access: grant the client-credentials client a read-only role covering
telephony (DIDs, pools, sites, trunks), architect (flows + IVR configurations),
routing and user directory read (the agent cross-reference). Optional extras:
outbound read (outbound:readonly) enables the caller-ID check, and
organization read (organization:readonly — a baseline scope on effectively every
client-credentials grant) fills the org-name banner.
Graceful degradation: every source is independently fenced. A missing scope
fails only its own stage — the scan log shows the per-source error, the per-source counters
([IVR:… A:… B:… C:… D:…]) show what contributed, inventory types that fail are listed as not fetched, and the outbound check reports “skipped” rather than aborting the
audit.
6Storage, privacy & security
No persistence. No database and no audit results retained on the server. Results exist only in the browser tab that ran the audit; a page reload empties the workspace until the next run.
Sessions — your credentials are held on the server only while you are signed in. Sessions end after a period of inactivity or when you sign out; if the service is restarted, everyone simply signs in again.
Credential handling — the browser sends the secret exactly once, at sign-in; thereafter it is held on the server and never sent back to the browser, and a fresh OAuth token is fetched per audit run. Sign-out destroys the credentials. The browser’s login hint stores Client ID + region only, never the secret.
Run isolation — each audit’s live progress and results can only be viewed by the session that started it.
Read-only against Genesys — the only non-GET request the app ever makes is the OAuth token call. DID Conflict Checker cannot modify anything in your org.
PII surface — audit results contain agent names, emails and phone numbers (that is the point of the conflict check). They are shown in your browser and land in exports you generate; treat exported files accordingly.
External requests from the browser — the page loads its fonts and the Excel/PDF export components from public providers. Audit data is never sent to them; the exports are built locally in your browser.
7Technology
Web application — a small, dependency-light service that signs in to Genesys, runs the audit server-side and streams progress to your browser.
Browser interface — a live scan log and result cards built in the browser from the audit results.
Exports — CSV, Excel and PDF are all generated in your browser; audit data never leaves it.
No database — every audit re-reads the org live.
8Troubleshooting
“The service is busy – try again shortly”
The service is handling as many sign-ins as it can. Signing in with the same Client ID and region reclaims your own earlier session automatically; otherwise try again shortly or ask a colleague to sign out.
Audit finishes but “0 numbers mapped”.
Read the ownerType breakdown on the Routing Source Analysis card. If the DIDs are owned by something other than IVR_CONFIG/flows (e.g. all USER), there are no flow assignments to find. The usual fix is in Genesys: Admin → Architect → IVRs — assign the numbers to IVR configurations. The zero-mapped banner repeats this hint.
“Session expired — please sign in again” right after clicking Run Audit.
The session ended after a period of inactivity, or the service was restarted. Sign in again.
Sources are independent and failures are non-fatal: the audit continues and the per-source counters ([IVR:… A:… B:… C:… D:…]) show what contributed. A persistently failing source usually means the OAuth client lacks that read permission. Sites whose number-plan endpoint returns 403/404/405 are skipped silently by design.
“⚠ Outbound check skipped: …”
The caller-ID cross-reference needs outbound read access (outbound:readonly). Without it the audit still completes — only the ghost-ring check is skipped.
Inventory card says “Could not fetch: BOT, WORKFLOW…”.
Genesys refused those flow types — the client credentials lack the scope for that flow category. Each type is fetched independently; everything else in the inventory is complete.
Live progress stops mid-run (“Disconnected”).
A brief network interruption, or the service was restarted in the background. Click Run Audit again; runs are cheap and stateless.
“This run belongs to another session”.
Each audit is bound to the session that started it. Start your own run.
Excel/PDF button does nothing, or says the export is not ready.
The export components load from the internet when the page loads. If the browser lacked internet access at that moment they are missing — reload with connectivity. CSV export has no such dependency.
An expected agent conflict wasn’t flagged.
Matching compares normalised numbers on equality or identical last 10 digits; numbers stored with fewer than 10 digits (short extensions) only match exactly. And only active users are harvested — deactivated users are ignored deliberately.
The flow link opens Architect on “latest”, not my edit.
Deep-links open the flow overview by design; task-level links need a task id the audit does not have.
The duplicate banner counts a number I think is fine.
Same-flow registrations from different sources are not counted — that is provenance overlap. A duplicate means two different flows; the extra assignments genuinely never fire.
QVCCS DID Conflict Checker — DID & number-to-flow audit for Genesys Cloud CX. Strictly read-only against the Genesys APIs; no results stored — every audit re-reads the org live.
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 DID Conflict Checker 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.