Powershell: HubSpot Leads API with 37Signals Highrise

This article demonstrates how you can integrate 37Signals Highrise CRM with your HubSpot Leads API using a PowerShell script.

In order to be able to access the Highrise RESTful API, you'll need to acquire your API key from the Highrise system. You can find this by logging into your Highrise portal, then clicking on the 'My Info' link at the top right hand side of the page, then clicking on the 'API Token' link. You'll also need the base URL for your Highrise portal. Typically this is in the format of '<yourcompany>.highrisehq.com' but it may vary in some instances.

If your going to copy the code below you will need to set the following variables to reflect your own API keys and Highrise url.

$HighriseUrl = "https://yourcompany.highrisehq.com/"
$HighriseApiToken = ""
$HubSpotApiToken = ""
# Update the following with your details
$HighriseUrl = "https://yourcompany.highrisehq.com"
$HighriseApiToken = ""
$HubSpotApiToken = ""

# http://powershelljson.codeplex.com
Function ConvertFrom-JSON {
    param(
        $json,
        [switch]$raw  
    )

    Begin
    {
     $script:startStringState = $false
     $script:valueState = $false
     $script:arrayState = $false 
     $script:saveArrayState = $false

     function scan-characters ($c) {
      switch -regex ($c)
      {
       "{" { 
        "(New-Object PSObject "
        $script:saveArrayState=$script:arrayState
        $script:valueState=$script:startStringState=$script:arrayState=$false    
           }
       "}" { ")"; $script:arrayState=$script:saveArrayState }

       '"' {
        if($script:startStringState -eq $false -and $script:valueState -eq $false -and $script:arrayState -eq $false) {
         '| Add-Member -Passthru NoteProperty "'
        }
        else { '"' }
        $script:startStringState = $true
       }

       "[a-z0-9A-Z@. ]" { $c }

       ":" {" " ;$script:valueState = $true}
       "," {
        if($script:arrayState) { "," }
        else { $script:valueState = $false; $script:startStringState = $false }
       } 
       "\[" { "@("; $script:arrayState = $true }
       "\]" { ")"; $script:arrayState = $false }
       "[\t\r\n]" {}
      }
     }
     
     function parse($target)
     {
      ForEach($c in $target.ToCharArray()) { 
       $result += scan-characters $c
      }
      $result  
     }
    }

    Process { 
        if($_) { $result = parse $_ } 
    }

    End { 
        If($json) { $result = parse $json }

        If(-Not $raw) {
            $result | Invoke-Expression
        } else {
            $result 
        }
    }
}

# Setup an Event Log
$EventLog = Get-EventLog -list | Where-Object {$_.Log -eq “Application”}
$EventLog.MachineName = “.”
$EventLog.Source = “HubSpot”

$EventLog.WriteEntry(“HubSpot to Highrise synchronisation started”,”Information”, 100)
# Check to see if there is an existing HubSpot.txt 
if(Test-Path "HubSpot.txt")
{
    # Read the time from the file that the job last ran
    $OldTime = Get-Date(Get-Content "HubSpot.txt")
    $EventLog.WriteEntry(“HubSpot to Highrise synchronisation last ran ” + $OldTime.ToString() ,”Information”, 100)
} else {
    # Set the time to now
    $OldTime = Get-Date
    $EventLog.WriteEntry(“HubSpot to Highrise synchronisation has never run before" ,”Information”, 100)
}
# Update the file with the current time
$file = New-Item -type file "HubSpot.txt" -Force
add-content $file (get-date).ToString()
# The following line is used for debugging purposes
#$OldTime = New-Object System.DateTime(2011,4,8,9,0,0)
# Epoch time represents the eqivalent of the PHP time() function
$EpochTime = New-Object System.DateTime(1970,1,1,0,0,0)
$StartTime = ($OldTime - $EpochTime).TotalSeconds
# Retrieve data from the HubSpot API
# The StartTime is in milliseconds so we add 3 0's to the end
$WebClient = New-Object System.Net.WebClient
$Response = $WebClient.DownloadString("https://hubapi.com/leads/v1/list/?hapikey=" + $HubSpotApiToken + "&startTime=" + $StartTime.ToString() + "000")
# Load the response text into a JSON object
$JSON = ConvertFrom-JSON $Response
if(!$JSON)
{
    # No results returned from HubSpot
    $EventLog.WriteEntry(“No new leads in HubSpot" ,”Information”, 100)
} else {
    # Process the new leads
    $EventLog.WriteEntry(“Found " + $JSON.Count.ToString() + " new leads in HubSpot" ,”Information”, 100)
    foreach($Lead in $JSON)
    {
        # Check to see if this lead already exists in Highrise
        $EventLog.WriteEntry(“Checking if " + $Lead.email + " exists in Highrise" ,”Information”, 100)
        $WebClient = New-Object System.Net.WebClient
        $WebClient.Credentials = new-object System.Net.NetworkCredential($HighriseApiToken, "X")
        $Response = $WebClient.DownloadString($HighriseUrl + "/people/search.xml?criteria[email]=" + $lead.email);
        if($Response.Contains("<nil-classes"))
        {
            $EventLog.WriteEntry("Creating contact record for " + $Lead.email + " in Highrise" ,”Information”, 100) 
            # Contruct new Highrise Person XML
            $Xml = "<person>"
            $Xml += "<first-name>" + $Lead.firstName + "</first-name>"
            $Xml += "<last-name>" + $Lead.lastName + "</last-name>"
            $Xml += "<title>" + $Lead.jobTitle + "</title>"
            $Xml += "<background>Found Site Via: " + $Lead.fullFoundViaString + "\n"
            $Xml += "First Visit: $convertDate\n"
            $Xml += "HubSpot Lead Grade: " + $Lead.score + "\n"
            $Xml += "Lead in HubSpot: " + $Lead.publicLeadLink + "\n"
            $Xml += "Number of Conversion Events: " + $Lead.numConversionEvents + "\n"
            $Xml += "UserToken: " + $Lead.userToken + "\n"
            $Xml += "IP Address: " + $Lead.ipAddress + "\n"
            $Xml += "HubSpot Guid: " + $lead.guid + "</background>"
            $Xml += "<visible-to>Everyone</visible-to>"
            $Xml += "<contact-data>"
            $Xml += "<email-addresses>"
            $Xml += "<email-address>"
            $Xml += "<address>" + $Lead.email + "</address>"
            $Xml += "<location>Work</location>"
            $Xml += "</email-address>"
            $Xml += "</email-addresses>"
            $Xml += "<phone-numbers>"
            $Xml += "<phone-number>"
            $Xml += "<number>" + $Lead.phone + "</number>"
            $Xml += "<location>Work</location>"
            $Xml += "</phone-number>"
            $Xml += "</phone-numbers>"
            $Xml += "<addresses>"
            $Xml += "<address>"
            $Xml += "<city>" + $Lead.city + "</city>"
            $Xml += "<country>" + $Lead.country + "</country>"
            $Xml += "<state>" + $Lead.state + "</state>"
            $Xml += "<street>" + $Lead.address + "</street>"
            $Xml += "<zip>" + $Lead.zip + "</zip>"
            $Xml += "<location>Work</location>"            
            $Xml += "</address>"
            $Xml += "</addresses>"
            $Xml += "<web-addresses>"
            $Xml += "<web-address>"
            $Xml += "<url>" + $Lead.website + "</url>"
            $Xml += "<location>Work</location>"
            $Xml += "</web-address>"
            $Xml += "</web-addresses>"
            $Xml += "</contact-data>"
            $Xml += "</person>"                       
            
            # POST the XML to Highrise API using the Token
            $WebClient = New-Object System.Net.WebClient
            $WebClient.Credentials = new-object System.Net.NetworkCredential($HighriseApiToken, "X")
            $WebClient.Headers.Add("Content-Type", "application/xml")
            Try
            {                      
                $WebClient.UploadString($HighriseUrl + "/people.xml", "POST", $Xml);  
                # Check the response and log status
                if($WebClient.ResponseHeaders["Status"] = "201 Created")
                {
                    $EventLog.WriteEntry("Contact record for " + $Lead.email + " successfully created in Highrise" ,”Information”, 100)     
                } else {
                    $Err = "Error creating contact record for " + $Lead.email + " in Highrise`n"
                    $Err += $WebClient.ResponseHeaders["Status"]
                    $EventLog.WriteEntry($Err ,”Error”, 100) 
                }         
            } Catch {
                # Trap and log any errors in the request
                $Err = "Error creating contact record for " + $Lead.email + " in Highrise:`n"
                $Err += $error[0]
                $EventLog.WriteEntry($Err ,”Error”, 100) 
            }                             
        } else {
            $EventLog.WriteEntry($Lead.email + " already exists in Highrise" ,”Information”, 100)                
        }        
    }
}
$EventLog.WriteEntry(“HubSpot to Highrise synchronisation completed" ,”Information”, 100)

1 comments:

ccefthfrhp said...

Heat dissipation and electrical insulation have been the principle design necessities on this case. covered plunger So, CNC machined anodized aluminum was ideal for their one-off customized enclosure. The capacity of manufacture quickly customized metallic components with great dimensional accuracy, makes CNC machining a beautiful option for producing useful prototypes. CNC machining has functions within the automotive industry when manufacturing of high-performance customized components is required. Use the desk beneath for a tough estimate of the fee per hour of the completely different CNC machines.