ServiceNow – Create an Incident Ticket Using PowerShell Via REST API

Do you need a PowerShell script to log ServiceNow ticket? You are in luck. When you marry up the ServiceNow API with PowerShell, amongst other methods, the possibilities are endless. One of the most common reasons I find you will want to integrate the two would be to log a service ticket as an incident on the back of an alert. These could be Microsoft alerts indicating you have an issue with AAD Connect or any other alert that could perhaps be Azure notifying you of a server with a high CPU.

This post will demonstrate a simple PowerShell function I have written. I use it regularly in production when logging a variety of alerts … although, I will leave you to take this model and apply it to your own environment. I would be interested to see what use cases you come up with.

Pre-requisites:

You may want to explore the following blogs that will help set the scene with what I am going to demonstrate.

PowerShell Script To Create ServiceNow Incident

Here is the code that I am going to demonstrate and I will step through it line by line as we go through the post.

# Set the credentials
$User = 'contoso.administrator'
$Pass = 'P4ssw0rd!!'

# Set headers
$GlobalHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$GlobalHeaders.Add('Accept', 'application/json')
$GlobalHeaders.Add('Content-Type', 'application/json')

# Build & set authentication header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $Pass)))
$GlobalHeaders.Add('Authorization', ('Basic {0}' -f $base64AuthInfo))

# Load variable with ServiceNow instance URL
$ServiceNowInstance = 'https://dev99999.service-now.com'
# Load a variable with the incident table API endpoint
$CreateIncidentURL = "$ServiceNowInstance/api/now/table/incident"
# Service Desk assignment group sys_id
$AssignmentGroup = 'd625dccec0a8016700a222a0f7900d06'
# Alan Ps1/contoso.administrator elevated user sys_id
$ContosoAdministrator = 'b9427790db3620106426f36f299619bf' # contoso.administrator

Function Add-Ticket {

    # Load a variable with data for the description field
    $MessageBody = "Here is some text ...`r`n`r`nYou could generate this data from anywhere.`r`nI will leave the rest to your imagination."
    # Load a variable with data for the short description field
    $ShortDescription = "New ticket logged from Powershell"
    
    # Splat some paramanters used for the body of the POST request
    $SNNewTicketData = @{
        short_description               = $ShortDescription
        description                     = $MessageBody
        category                        = "Software"
        u_type                          = "incident"
        assignment_group                = $AssignmentGroup
        caller_id                       = $ContosoAdministrator
    }

    # Splat some paramanters used for the POST request, Headers, Method, Uri all required
    # Body used to pass the fields I will pupulate within the ticket - there are several, see the docs
    $Params = @{
        Headers = $GlobalHeaders
        Method  = "POST"
        Uri     = $CreateIncidentURL
        Body    = ($SNNewTicketData | ConvertTo-Json)
    }

    # God practice, although in this example I am not handling any errors. Maybe you can to suit?
    Try {

        Invoke-WebRequest @Params -UseBasicParsing -ErrorAction Stop

    }
    Catch {

        # Handle any errors

    }

}

# Run the function, Add-Ticket
Add-Ticket

Assuming you have had a flick through the pre-requisites or are already familiar with these. I will provide a quick summary of the code that sits out with the function, Add-Ticket. This is lines 1 through 21 in the code snippet above.

  • 1 through 3 – Sets the Username & Password of the elevated user that has rights to log a ticket using basic authentication
  • 5 through 8 – Creates a dictionary used for the POST headers. Set's content-type & accept to "application/json"
  • 10 through 12 – Converts the username & password to a Base64 string and adds Authorization set to Basic in the headers
  • 14 through 17 – Loads some variables with the all important Instance url & Endpoint which is the incident table url
  • 18 through 21 – These are the sys_id(s) for both the Service Desk assignment group and the Alan Ps1 elevated admin user

I am going to now elaborate on lines 18 through 21 as there are several ways to get the sys_id for a user or an assignment group. My preferred method when working in development is to simply access the record you want the sys_id for and copy it straight to the clipboard. See below:

Would you like to buy Alan a coffee?

Visit the AlanPs1 Ko-fi page

Your guid, or sys_id are likely to vary from mine. So be sure to investigate and capture the values of the users and groups you will be using when deploying the function Add-Ticket… Now for the function.

PowerShell Function in Script to Log ServiceNow Ticket

  • 25 through 28 – Load two x variables. One with string data for the description, one with string data for a short description
  • 30 through 38 – Splatting used to neatly collate the data required for the request body
  • 40 through 47 – Splatting used to collate the parameters required to make the request
  • 49 through 59 – Try Catch to send the all-important command, Invoke-WebRequest with @params from above
  • 63 through 64 – Invoke the function that will, in turn, send the request

This method will now log a service ticket in ServiceNow marked as incident. Let's have a look at an image that displays the fruits of our labour.

Now you can try it for yourself. You may want to flip from logging an incident to a Change Request, you may also have custom tables and could be using different fields like custom HTML fields perhaps. The tickets you may log may also trigger workflows in ServiceNow. Let's see what you use this for.

Thanks for reading, Alan.