Service Hooks are Visual Studio Team Services way of integrating with other web applications by automatically sending them events when specific things happen in VSTS, like a build completes or code is committed.

These are what I used in my earlier post about integrating VSTS with TeamCity</a>. If you just have one service hook to set up then using the web UI is fine, but if you find yourself doing something again and again then finding a way to automate it can be really useful.

Interacting with service hooks via VSTS REST API is documented here. Web Hooks are a particular service hook 'consumer' suitable for sending HTTP messages to any web endpoint.

I'm going to create a PowerShell script which requires the following parameters

Param(
   [string]$vstsAccount,
   [string]$projectName,
   [string]$repositoryName,
   [string]$token
)

Using the VSTS APIs requires authentication, so the first thing is to encode a Personal Access Token (PAT) so it can be set as a HTTP header. (You create PATs from the Web UI by clicking on your profile picture and selecting Security)

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "",$token)))

There's a whole lot of VSTS events that you can choose as a trigger when creating a service hook. In this example, I'm interested in being notified when a Git pull request is created. In order to use this particular API, I need to also know the ids of the VSTS Project and Repository that I want this service hook associated with. I'll use API calls to find those out.

$uri = "https://$($vstsAccount).visualstudio.com/_apis/projects?api-version=5.0-preview.1"
$result = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$projectId = $result.value | Where-Object { $_.name -eq $projectName } | Select-Object -ExpandProperty id

$uri = "https://$($vstsAccount).visualstudio.com/_apis/git/repositories?api-version=5.0-preview.1"
$result = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$repositoryId = $result.value | Where-Object { $_.name -eq "$repositoryName" } | Select-Object -ExpandProperty id

As far as the REST API is concerned, we're creating a new 'subscription'. Create operations use a POST and usually also require JSON data to be sent in the body. We'll use PowerShell to model the data and then convert it back to a JSON string:

$body = @{
    "publisherId" = "tfs"
    "eventType" = "git.pullrequest.created"
    "resourceVersion" = "1.0"
    "consumerId" = "webHooks"
    "consumerActionId" = "httpRequest"
    "publisherInputs" = @{
        "projectId" = $projectId
        "repository" = $repositoryId
        "branch" = ""
        "pullrequestCreatedBy" = ""
        "pullrequestReviewersContains" = ""
    }
    "consumerInputs" = @{
        "url" = "https://servicetonotify"
        "basicAuthUsername" = ""
        "basicAuthPassword" = ""
        "resourceDetailsToSend" = "all"
        "messagesToSend" = "none"
        "detailedMessagesToSend" = "none"
    }
}

$bodyJson = $body | ConvertTo-Json

Obviously you will need to customise the url value to point to your particular web service that should be notified. If that service requires authentication, you can supply a username and password in the basicAuthUsername and basicAuthPassword values. You can also control what detailed information VSTS will send to by setting the three *ToSend values. In my case I only needed resourceDetailsToSend but not the other two.

$uri = "https://$($vstsAccount).visualstudio.com/_apis/hooks/subscriptions?api-version=5.0-preview.1"
Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $bodyJson

Using the VSTS REST API is pretty straight forward, and gives you great access to query and modify your VSTS environment.