Using the Statuscake API with Powershell

Having set up a few URL monitors with Statuscake, I needed to get the data out to start playing with it in Microsoft Excel/PowerQuery.
There are 3 sets of data that i’m extracting with the script below.

    Location data
    Test definition data
    Test Performance data

On top of the basic API calls to Statuscake I wanted to enrich their Location data with actual Geo data that could be used in a BI visualisation. For this i’m using FreeGeoIP.

#Statuscake
$baseurl = "https://www.statuscake.com/API"
$testurl = "$baseurl/Tests/"
$locationsurl="$baseurl/Locations/json"
$username ="yourUsername"
$accesskey ="yourApiAccessKey"
$authHeaders = @{"Username"="$username";"API"="$accesskey"}
$outFolder = "C:statuscake"

$dateStr = get-date -Format "yyyyMMdd-HHmm"

#Get location data
Write-Host "Fetching remote location data"
$lResponse = Invoke-WebRequest $locationsurl -Headers $authHeaders
$rawLocations = $lResponse.content | ConvertFrom-Json
$locations = $rawLocations | gm -MemberType NoteProperty | ForEach-Object { $rawLocations."$($_.Name)"  } 

#Resolve geo-location info from IP address
Write-Host "Fetching geo-location data for Statuscake servers"
$locations | Add-Member -MemberType NoteProperty -Name "CountryCode" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "CountryName" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "RegionCode" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "RegionName" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "City" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "Zipcode" -Value ""
$locations | Add-Member -MemberType NoteProperty -Name "Latitude" -Value 0.0
$locations | Add-Member -MemberType NoteProperty -Name "Longitude" -Value 0.0

foreach($location in $locations) {
    $geoUrl="http://freegeoip.net/xml/" + $location.ip
    $geoResponse = Invoke-WebRequest $geoUrl -UseBasicParsing 
    $geoData = ([xml]$geoResponse.Content).Response
    
    $location.CountryCode= $geoData.CountryCode
    $location.CountryName= $geoData.CountryName
    $location.RegionCode= $geoData.RegionCode
    $location.RegionName= $geoData.RegionName
    $location.City= $geoData.City
    $location.Zipcode= $geoData.Zipcode
    $location.Latitude= $geoData.Latitude
    $location.Longitude= $geoData.Longitude
}    
$locations | Export-Csv "$outFolderlocations.csv" -NoTypeInformation -force

#Get all tests
Write-Host "Fetching test definitions"
$hResponse = Invoke-WebRequest "$testurl$paramstring" -Headers $authHeaders
$allTests = $hResponse.content | ConvertFrom-Json
$allTests | Export-Csv "$outFolderalltests-$dateStr.csv" -NoTypeInformation

#Get perf data
foreach ($test in $allTests) {
    Write-Host "Fetching perf data for: " $test.WebsiteName

    $specificTestUrl = $testUrl + "Checks?TestID=" + $test.TestID + "&Fields=status,location,time,performance";
    $hResponse = Invoke-WebRequest $specificTestUrl -Headers $authHeaders
    $rawData = $hResponse.content | ConvertFrom-Json
    $perfdata = $rawData | gm -MemberType NoteProperty | ForEach-Object { $rawData."$($_.Name)"  }
    
    $perfdata | Add-member -MemberType NoteProperty -Name "TestId" -Value $test.TestID
    $perfdata | Add-member -MemberType NoteProperty -Name "DateTime" -value ""
    $perfdata | Add-Member -MemberType NoteProperty -Name "LocationIP" -Value ""

    foreach($perfItem in $perfdata) {
        $perfItem.LocationIP = ($locations | Where-Object{$_.Servercode -eq $perfItem.Location} | Select-Object ip).ip
        $perfItem.DateTime = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($perfItem.Time))
    } 
    
    $test | Add-Member -MemberType NoteProperty -Name "PerfData" -Value $perfdata
}

#output to csv
$alltests  | Select-Object -ExpandProperty PerfData  | Export-Csv "$outFolderperfdata-$dateStr.csv" -NoTypeInformation