Private/ClickUpAPI.ps1

function Invoke-ClickUpAPIRequest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Default', 'Get', 'Head', 'Post', 'Put', 'Delete', 'Trace', 'Options', 'Merge', 'Patch')]
        [string]$Method,
        [Parameter(Mandatory = $true)]
        [string]$URI,
        [hashtable]$Body
    )
    try {
        $InvokeParams = @{
            Body        = if ($Body) { ConvertTo-Json -InputObject $Body -Depth $ClickUpJSONConversionDepth } else { '' }
            ContentType = 'application/json'
            Headers     = @{
                Authorization = Get-ClickUpAPIKeyInsecure -APIKey $ClickUpAPIKey
            }
            Method      = $Method
            Uri         = $URI
        }
        $Response = Invoke-RestMethod @InvokeParams
        if ($Response) {
            return $Response
        }
    } catch {
        $ErrorMessage = "Failed to invoke ClickUp API request. Method: $Method, URI: $URI"

        # Attempt to extract more detailed error information from the response
        if ($_.Exception.Response) {
            try {
                $Stream = $_.Exception.Response.GetResponseStream()
                if ($Stream) {
                    $Reader = [System.IO.StreamReader]::new($Stream)
                    $ResponseBody = $Reader.ReadToEnd()
                    $ErrorMessage += ". Response: $ResponseBody"
                }
            } catch {
                # Ignore errors reading the response stream
            }
        } else {
            $ErrorMessage += ". Error: $($_.Exception.Message)"
        }

        Write-Error $ErrorMessage
        throw $ErrorMessage
    }
}

function Invoke-ClickUpAPIGet {
    [CmdletBinding()]
    param (
        [hashtable]$Arguments = @{},
        [Parameter(Mandatory = $true)]
        [string]$Endpoint
    )
    if ($Arguments.Count) {
        $URI = New-HTTPQueryString -Uri "https://api.clickup.com/api/v2/$Endpoint" -QueryParameter $Arguments
    } else {
        $URI = "https://api.clickup.com/api/v2/$Endpoint"
    }
    $Response = Invoke-ClickUpAPIRequest -Uri $URI -Method 'Get'
    return $Response
}

function Invoke-ClickUpAPIPost {
    [CmdletBinding()]
    param (
        [hashtable]$Arguments = @{},
        [Parameter(Mandatory = $true)]
        [string]$Endpoint,
        [Parameter(Mandatory = $true)]
        [hashtable]$Body
    )
    if ($Arguments.Count) {
        $URI = New-HTTPQueryString -Uri "https://api.clickup.com/api/v2/$Endpoint" -QueryParameter $Arguments
    } else {
        $URI = "https://api.clickup.com/api/v2/$Endpoint"
    }
    $Response = Invoke-ClickUpAPIRequest -Uri $URI -Method 'Post' -Body $Body
    return $Response
}

function Invoke-ClickUpAPIPut {
    [CmdletBinding()]
    param (
        [hashtable]$Arguments = @{},
        [Parameter(Mandatory = $true)]
        [string]$Endpoint,
        [Parameter(Mandatory = $true)]
        [hashtable]$Body
    )
    if ($Arguments.Count) {
        $URI = New-HTTPQueryString -Uri "https://api.clickup.com/api/v2/$Endpoint" -QueryParameter $Arguments
    } else {
        $URI = "https://api.clickup.com/api/v2/$Endpoint"
    }
    $Response = Invoke-ClickUpAPIRequest -Uri $URI -Method 'Put' -Body $Body
    return $Response
}

function Invoke-ClickUpAPIDelete {
    [CmdletBinding()]
    param (
        [hashtable]$Arguments = @{},
        [Parameter(Mandatory = $true)]
        [string]$Endpoint
    )
    if ($Arguments.Count) {
        $URI = New-HTTPQueryString -Uri "https://api.clickup.com/api/v2/$Endpoint" -QueryParameter $Arguments
    } else {
        $URI = "https://api.clickup.com/api/v2/$Endpoint"
    }
    $Response = Invoke-ClickUpAPIRequest -Uri $URI -Method 'Delete' -Body $Body
    return $Response
}

function Invoke-ClickUpAPIPostAttachment {
    [CmdletBinding()]
    param (
        [hashtable]$Arguments = @{},
        [Parameter(Mandatory = $true)]
        [string]$Endpoint,
        [Parameter(Mandatory = $true)]
        [string]$Body,
        [Parameter(Mandatory = $true)]
        [string]$Boundary
    )
    if ($Arguments.Count) {
        $URI = New-HTTPQueryString -Uri "https://api.clickup.com/api/v2/$Endpoint" -QueryParameter $Arguments
    } else {
        $URI = "https://api.clickup.com/api/v2/$Endpoint"
    }

    $InvokeParams = @{
        Body        = $Body
        ContentType = "multipart/form-data; boundary=`"$Boundary`""
        Headers     = @{
            Authorization = Get-ClickUpAPIKeyInsecure -APIKey $ClickUpAPIKey
        }
        Method      = 'post'
        Uri         = $URI
    }

    try {
        $Response = Invoke-RestMethod @InvokeParams
        return $Response
    } catch {
        $ErrorMessage = "Failed to upload attachment to $URI"

        if ($_.Exception.Response) {
            try {
                $Stream = $_.Exception.Response.GetResponseStream()
                if ($Stream) {
                    $Reader = [System.IO.StreamReader]::new($Stream)
                    $ResponseBody = $Reader.ReadToEnd()
                    $ErrorMessage += ". Response: $ResponseBody"
                }
            } catch {
                # Ignore errors reading the response stream
            }
        } else {
            $ErrorMessage += ". Error: $($_.Exception.Message)"
        }

        Write-Error $ErrorMessage
        throw $ErrorMessage
    }
}