Public/Get-DattoApiOperation.ps1

function Get-DattoApiOperation {
<#
.SYNOPSIS
Lists operations from the bundled Datto OpenAPI contract.
.DESCRIPTION
Reads the exact OpenAPI contract shipped with the module. Use -Detailed to obtain each complete operation object, including parameters, request body, responses, and schema references.
.PARAMETER OperationId
Filters operation IDs. Wildcards are supported.
.PARAMETER Path
Filters API paths. Wildcards are supported.
.PARAMETER Tag
Filters by OpenAPI tag.
.PARAMETER Method
Filters by HTTP method.
.PARAMETER Detailed
Includes the complete OpenAPI operation object.
.EXAMPLE
Get-DattoApiOperation
.EXAMPLE
Get-DattoApiOperation -Tag 'SaaS Protection' -Detailed
.OUTPUTS
PSCustomObject
#>

    [CmdletBinding()]
    param(
        [Parameter()]
        [SupportsWildcards()]
        [string]$OperationId = '*',

        [Parameter()]
        [SupportsWildcards()]
        [string]$Path = '*',

        [Parameter()]
        [SupportsWildcards()]
        [string]$Tag = '*',

        [Parameter()]
        [ValidateSet('GET', 'PUT')]
        [string]$Method,

        [Parameter()]
        [switch]$Detailed
    )

    $spec = Get-DattoApiSpecificationDocument
    foreach ($pathProperty in $spec.paths.PSObject.Properties) {
        foreach ($methodProperty in $pathProperty.Value.PSObject.Properties) {
            $methodName = $methodProperty.Name.ToUpperInvariant()
            if ($methodName -notin @('GET', 'PUT')) { continue }
            $operation = $methodProperty.Value
            $tags = @()
            if ($operation.PSObject.Properties.Name -contains 'tags') { $tags = @($operation.tags) }
            $operationIdValue = ''
            if ($operation.PSObject.Properties.Name -contains 'operationId') { $operationIdValue = [string]$operation.operationId }
            if ($operationIdValue -notlike $OperationId) { continue }
            if ([string]$pathProperty.Name -notlike $Path) { continue }
            if ($PSBoundParameters.ContainsKey('Method') -and $methodName -ne $Method) { continue }
            if (-not (@($tags | Where-Object { $_ -like $Tag }).Count -gt 0)) { continue }

            $parameterCount = 0
            if ($operation.PSObject.Properties.Name -contains 'parameters') { $parameterCount = @($operation.parameters).Count }
            $successResponses = @($operation.responses.PSObject.Properties.Name | Where-Object { $_ -match '^2' })
            $summaryValue = ''
            $descriptionValue = ''
            if ($operation.PSObject.Properties.Name -contains 'summary') { $summaryValue = [string]$operation.summary }
            if ($operation.PSObject.Properties.Name -contains 'description') { $descriptionValue = [string]$operation.description }
            $record = [ordered]@{
                Method           = $methodName
                Path             = [string]$pathProperty.Name
                OperationId      = $operationIdValue
                Tags             = $tags
                Summary          = $summaryValue
                Description      = $descriptionValue
                ParameterCount   = $parameterCount
                HasRequestBody   = ($operation.PSObject.Properties.Name -contains 'requestBody')
                SuccessResponses = $successResponses
            }
            if ($Detailed) { $record['Operation'] = $operation }
            [pscustomobject]$record
        }
    }
}