Loading...

Pull Table data from ServiceNow Instance using REST API

Pull Table data from ServiceNow Instance using REST API

ServiceNow REST API enables you to access Instance resources. You can create, read, update, and delete records on your ServiceNow instance after registering your application and getting authentication tokens for a user or resource.

To create the ServiceNow API Client ID and Client Secret, follow the steps listed in this article.

servicenow-get-table-data-api-registration.png (Example Application Registration)

ServiceNow authentication validates the identity of a user who accesses an instance and then authorizes the user to features that match the user’s role or job function. You can use several different methods to authenticate users. We are using the password grant type approach here.

The ServiceNow Table API allows you to perform operations on existing tables.

Servicenow recommends exporting data in chunks in case of extensive data set with millions of records to avoid any performance implications and impact on other services running on the system. The Aggregate API allows you to get statistics about the existing table and retrieve records by using the pagination technique.

Sample Script

This sample script shows how to pull data from ServiceNow Table and print the table details in the console window.

# ServiceNow Instance Configuration
$servicenowInstance = @{
    Name            = "your_instance_name" # ServiceNow Instance Name
    APIVersion      = "api/now/v1" # ServiceNow API Version
    ClientID        = $env:ServiceNowClientID # To be set in the environment
    ClientSecret    = $env:ServiceNowClientSecret # To be set in the environment
    Username        = $env:ServiceNowUsername # To be set in the environment
    Password        = $env:ServiceNowPassword # To be set in the environment
    ItemsPerAPICall = 100 # Number of items to be retrieved in a single API call
}

# Get Acccess Token from ServiceNow
Function GetAccessToken () {
    try {
        Write-Host "Getting Access Token" -ForegroundColor Green 
    
        $headers = @{
            "Content-Type" = "application/x-www-form-urlencoded"
            "Accept"       = "application/json"
        }

        $body = @{
            grant_type    = "password"
            username      = $servicenowInstance.Username 
            password      = $servicenowInstance.Password
            client_id     = $servicenowInstance.ClientID
            client_secret = $servicenowInstance.ClientSecret
        }
    
        $tokenEndpoint = "https://$($servicenowInstance.Name).service-now.com/oauth_token.do"
        $response = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Headers $headers -Body $body

        if ($response.access_token) {
            $accessToken = $response.access_token
            Write-Host "Here is the Access Token" -ForegroundColor Green
            Write-Host "$accessToken" -ForegroundColor Green -BackgroundColor Green
            return $accessToken
        }
        else {
            Write-Host "There is a problem in getting Access Token. Error: $($response.status) - $($response.error_description)" -ForegroundColor Red
            return $null
        }
    }
    catch {
        throw "There is a problem in getting Access Token. Error: $($_.Exception.Message)"
    }
}

# Get Table Data from ServiceNow
Function GetTableData () {
    [CmdletBinding()]
    param (
        [Parameter()][string]$AccessToken, [Parameter()][string]$TableName, [Parameter()][string]$Query
    )
    try {
        Write-Host "Getting $($TableName) Table Data" -ForegroundColor Green

        $headers = @{
            "Accept"        = "application/json"
            "Authorization" = "Bearer $($AccessToken)"
        }

        $statsEndpoint = "https://$($servicenowInstance.Name).service-now.com/$($servicenowInstance.APIVersion)/stats/$($TableName)?sysparm_query=$($Query)&sysparm_count=true"
        $response = Invoke-RestMethod -Uri $statsEndpoint -Method Get -Headers $headers
        [int]$numberOfRecords = $($response.result.stats.count)
        Write-Host "Number of Records found in $($TableName): $($numberOfRecords)" -ForegroundColor Green
        $iterations = [Math]::Ceiling($numberOfRecords / $($servicenowInstance.ItemsPerAPICall))
        Write-Host "Number of iterations required to get all the records from this table : $($iterations)" -ForegroundColor Green

        $tableData = $null

        for ($i = 0; $i -lt $iterations; $i++) {
            $offset = $($i * $($servicenowInstance.ItemsPerAPICall))
            $query = "$($Query)&sysparm_display_value=all&sysparm_limit=$($servicenowInstance.ItemsPerAPICall)&sysparm_offset=$($offset)"
            $tableDataEndpoint = "https://$($servicenowInstance.Name).service-now.com/$($servicenowInstance.APIVersion)/table/$($TableName)?sysparm_query=$($query)"
            $response = Invoke-RestMethod -Uri $tableDataEndpoint -Method Get -Headers $headers
            $tableData += $($response.result)
        }

        return $tableData
    }
    catch {
        Write-Host "There is a problem in getting $($TableName) Table Data. Error: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# Print Table Data
Function PrintTableData () {
    
    param (
        $TableData
    )

    foreach ($record in $TableData) {
        $recordNumber = $record.number.display_value
        $recordSysId = $record.sys_id.display_value
        $first3CharsOfNumber = [string]$recordNumber.SubString(0, 3)
        
        switch ($first3CharsOfNumber) {
            "CHG" { $tableName = "change_request"; break }  
            "INC" { $tableName = "incident"; break }
            "TAS" { $tableName = "sc_task"; break }
            default { $tableName = $null; break }
        }

        if ($tableName) {
            $recordLink = "https://$($servicenowInstance.Name).service-now.com/nav_to.do?uri=$($tableName).do?sys_id=$($recordSysId)"
            Write-Host "Record Number: $($recordNumber) - Record Link: $($recordLink)" -ForegroundColor Green
        }
        else {
            Write-Host "Unable to create Record Link for $($recordNumber)" -ForegroundColor Red
        }
    }
}

# ****** Main Script Starts ******

try {
    $accessToken = GetAccessToken

    if ($accessToken) {
        $executionTime = [DateTime]::Now
        $oneYearBefore = $executionTime.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")
        $tableData = GetTableData -AccessToken $accessToken -TableName "incident" -Query "sys_created_on>=$($oneYearBefore)^assigned_to=^ORDERBYsys_created_on"
        
        if ($tableData.Count -gt 0) {
            PrintTableData -TableData $tableData
            Write-Host "Successfully got the data" -ForegroundColor Green
        }
        else {
            Write-Host "There is no data in the table" -ForegroundColor Yellow
        }
    }
    else {
        Write-Host "Access Token is empty/null" -ForegroundColor Red
    }
}
catch {
    Write-Host "There is a problem in running this script. Error: $($_.Exception.Message)" -ForegroundColor Red    
}

# ****** Main Script Ends ******

Sample Script Execution Output

servicenow-get-table-data-output.png

Published on:

Learn more
Home | Joseph Velliah
Home | Joseph Velliah

Fulfilling God’s purpose for my life

Share post:

Related posts

Vasanam Studio: How I Built a Bible Verse Video Generator for My Church as a Hobby Project

Every morning at 5 AM, the women of my church gather for prayer. At the end of the session, our pastor’s wife shares a Bible verse and sends a...

2 months ago

The demo worked. That was the problem.

Over a weekend I built a small Kubernetes demo to play with zero trust. Three little services calling each other in a chain, a login page in f...

2 months ago

Notes from building an agent on AgentCore end to end

I wanted a reason to use AgentCore end to end. Runtime, memory, guardrails, identity, the whole thing. A Bible Q&A agent felt like a good ...

4 months ago

Building a Rust gRPC AI Security Gateway for LLM Traffic

I wanted a small, honest implementation of the GenAI governance shape in code: a component on every LLM call that applies policy first, option...

4 months ago

Claude Code Security: The Smart Way to Integrate AI

Anthropic just dropped Claude Code Security, and if you’re anywhere near AppSec or DevSecOps, you’ve probably already seen the debate lighting...

5 months ago

How I Built a Semantic Cache Using Only AWS Services

LLM calls are expensive and slow, but here’s the thing - users ask the same questions in different ways all the time. “What’s your refund poli...

6 months ago

How to Build Better AI Agent Tools: Cut Costs by 70% (MCP Server Case Study)

Building tools for AI agents isn’t the same as building regular APIs. This guide shows you how to design tools that reduce token costs by 60-7...

6 months ago

Building a DevSecOps Pipeline on AWS (And You Can Too)

I have been working with CI/CD pipelines for a while now, and honestly, most of them just focus on getting code deployed fast. But what about ...

7 months ago

AWS DevOps Agent: AI-Powered Incident Investigation in Seconds

Stop spending 30 minutes investigating incidents. Let AI do it in seconds. Here is a hands-on demo you can practice in 15 minutes. The Proble...

8 months ago

DynamoDB Just Made Your Life Easier: Multi-Attribute Composite Keys Explained

AWS just dropped a feature on November 19, 2025 that is going to save you from one of DynamoDB’s most annoying workarounds: multi-attribute co...

8 months ago

Newsletter

Get the latest Dynamics 365 and Power Platform content in your inbox

A curated digest of community blogs, product news, videos, and podcasts — delivered without the noise.

Weekly updates Unsubscribe anytime Fresh community picks
We use your email only for the newsletter and you can unsubscribe at any time.
By subscribing, you agree to the privacy policy.