Private/Resolve-SCAUri.ps1

function Resolve-SCAUri {
    <#
    .SYNOPSIS
        Builds the full request URI for a CyberArk service call.
    .DESCRIPTION
        Combines a session's tenant subdomain with the base host for the target service, expands
        {placeholder} path parameters, and appends a query string. Base hosts follow the server
        values published in each service's own OpenAPI definition (see docs/API-INVENTORY.md for
        the source of each one, and the noted CDS host discrepancy).
    .PARAMETER Session
        A psSCA.Session object as returned by New-SCASession / Get-SCASession.
    .PARAMETER Service
        The CyberArk service that owns the endpoint being called.
    .PARAMETER Path
        The endpoint path, e.g. '/access/{csp}/eligibility'. May contain {name} placeholders.
    .PARAMETER PathParameters
        Hashtable used to expand {name} placeholders in Path.
    .PARAMETER QueryParameters
        Hashtable converted to a query string via New-SCAQueryString.
    .OUTPUTS
        System.String
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory)]
        [psobject]$Session,

        [Parameter(Mandatory)]
        [ValidateSet('SCA', 'UAP', 'UAR', 'CDS', 'CEM', 'Compass')]
        [string]$Service,

        [Parameter(Mandatory)]
        [string]$Path,

        [hashtable]$PathParameters,

        [hashtable]$QueryParameters
    )

    $tenant = $Session.TenantSubdomain

    $baseHost = switch ($Service) {
        'SCA' { "https://$tenant.sca.cyberark.cloud/api" }
        'UAP' { "https://$tenant.uap.cyberark.cloud/api" }
        'UAR' { "https://$tenant.uar.cyberark.cloud/api" }
        'CDS' { "https://$tenant.cds.cyberark.cloud" }
        'CEM' { "https://$tenant.cem.cyberark.cloud" }
        'Compass' { "https://$tenant.compass.cyberark.cloud/api" }
    }

    $resolvedPath = $Path
    if ($PathParameters) {
        foreach ($key in $PathParameters.Keys) {
            $encoded = [System.Uri]::EscapeDataString([string]$PathParameters[$key])
            $resolvedPath = $resolvedPath -replace "\{$key\}", $encoded
        }
    }

    if ($resolvedPath -match '\{[^}]+\}') {
        throw "Resolve-SCAUri: unresolved path placeholder(s) remain in '$resolvedPath'. Supply a value via -PathParameters."
    }

    $uri = "$baseHost$resolvedPath"

    $queryString = New-SCAQueryString -Parameters $QueryParameters
    if ($queryString) {
        $uri = "$uri`?$queryString"
    }

    return $uri
}