public/Add-Attachment.ps1

function Add-Attachment {
    <#
    .DESCRIPTION
    Utilized for associating a known attachment residing in the VSTS attachment store to a VSTS work item.
     
    .PARAMETER InstanceName
    The specific name of the VSTS instance to the attachment will be sent to.
    Example value would be CONTOSO where VSTS URL is https://contoso.visualstudio.com
     
    .PARAMETER WorkItemId
    The ID value of the VSTS work item to associate the attachment with.
     
    .PARAMETER AttachmentURI
    The full URI to the attachment that will be associate with the work item.
    The attachment must already reside in the VSTS attachment store.
     
    .PARAMETER APIKey
    The PAT (Personal Access Token) API Key with work item rights.
     
    .PARAMETER APIVersion
    The specific REST API version to utilize.
     
    .EXAMPLE
    Add-Attachment -InstanceName 'contoso' -WorkItemId 123 -AttachmentURI 'https://contoso.visualstudio.com/DefaultCollection/_apis/wit/attachments/15b09167-5edb-48f5-a893-dd3c3da131c2?fileName=Test.pdf' -APIKey 'odzhygw6smyztbvqwkv7cqcnl6tddqakvdojjdjo7yz4f6a3cf8a' -APIVersion '1.0'
    #>

    [CmdletBinding()]
    param (
        # VSTS Instance Name
        [Parameter(Mandatory=$true)]
        [string]
        $InstanceName,
        # The workitem id to associate the attachment with.
        [Parameter(Mandatory=$true)]
        [int]
        $WorkItemId,
        # Full URI for attachment within the VSTS attachment store.
        [Parameter(Mandatory=$true)]
        [string]
        $AttachmentURI,
        # VSTS API Key
        [Parameter(Mandatory=$true)]
        [string]
        $APIKey,
        # API Version
        [Parameter(Mandatory=$true)]
        [string]
        $APIVersion
    )
    process {
        $authHeader = @{Authorization = ("Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($apiKey)")))}

        $uri = "https://$($instanceName).visualstudio.com/DefaultCollection/_apis/wit/workitems/$($workItemId)?api-version=$($apiVersion)"

        $reqBody = @(
            @{
                path = '/relations/-'
                op = 'add'
                value = @{
                    rel = 'AttachedFile'
                    url = $attachmentURI
                }
            }
        )
        try {
            $result = Invoke-RestMethod -Method Patch -Headers $authHeader -Uri $uri -Body (ConvertTo-Json $reqBody -Depth 10) -ContentType 'application/json-patch+json' -ErrorAction Stop
            return $result
        }
        catch {
            throw "Failed to associate $($attachmentURI) with work item id $($workItemId) due to the following exception.`r`n$($_))"
        }
    }
}