Introduction
ServiceNow's Table API provides full CRUD access to any record in the platform. Combine that with PowerShell, and you unlock the ability to automate ticketing, compliance tracking, CMDB updates, and more — right from the command line.
In this article, you'll learn how to:
- Authenticate using Basic Auth, OAuth2 password grant (and why to avoid it), and OAuth2 Client Credentials grant (the current recommended approach)
- Make your first Table API call from PowerShell
- Parse and handle JSON responses
- Set the stage for advanced integration in later posts
1. Basic Authentication Setup
This is the simplest approach, but it's not recommended for production. Basic Auth sends credentials with every single request, which is why it's generally treated as a legacy pattern for anything beyond quick local testing.
# Replace with your instance and credentials
$instance = "dev12345"
$user = "admin"
$pass = "your_password"
$base64Auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$user`:$pass"))
# Define headers and URL
$headers = @{
"Authorization" = "Basic $base64Auth"
"Accept" = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"
# Call the API
$response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
# Output the result
$response.result
⚠️ Tip: Avoid hardcoding passwords, even for quick testing. Basic Auth is fine for a five-minute experiment against a Personal Developer Instance — don't build anything real on top of it.
2. OAuth2 Password Grant — and Why to Avoid It for New Work
This is the grant type shown in most older ServiceNow + PowerShell tutorials, including earlier drafts of this one. It's worth understanding, but it's no longer the right choice for anything new:
Prerequisites:
- OAuth enabled in ServiceNow
- A registered app with Client ID and Client Secret
- A user account with API access
# Credentials and endpoint
$clientId = "your_client_id"
$clientSecret = "your_client_secret"
$username = "admin"
$password = "your_password"
$instance = "dev12345"
$tokenUrl = "https://$instance.service-now.com/oauth_token.do"
# Build request body
$body = @{
grant_type = "password"
client_id = $clientId
client_secret = $clientSecret
username = $username
password = $password
}
# Get token
$response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$accessToken = $response.access_token
# Make Table API request
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"
$data = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
$data.result
Why this isn't actually the secure upgrade it looks like: this is the Resource Owner Password Credentials ("password") grant — and it's explicitly deprecated per current OAuth 2.0 security guidance, not just an older option among equals. Notice that it still requires the literal user password in the request body, which means switching from Basic Auth to this grant type doesn't actually solve the "avoid hardcoding passwords" problem — it just moves the same password from a request header into a request body. If you're on an older instance that doesn't yet support the grant type below, this remains a working fallback. For anything new, use Client Credentials instead.
3. OAuth2 Client Credentials Grant (Recommended)
Available since the Washington DC release, this grant is purpose-built for exactly this scenario — a script or service authenticating as itself, with no specific human user's password involved at all.
Prerequisites:
- OAuth enabled in ServiceNow
- A registered application configured for the Client Credentials grant, with an associated OAuth Application User (a dedicated service account used as the identity context for the token — configure this with the "Web service access only" / "Internal Integration User" option so it can't log into the UI and isn't subject to normal password expiration policies)
- On Zurich and later, register this through System OAuth > Application Registry > New Inbound Integration Experience > New Integration > OAuth – Client Credentials grant. On older releases, use Create an OAuth API endpoint for external clients instead — the underlying mechanism is the same, just a different registration screen.
# Credentials and endpoint — no username or password needed
$clientId = "your_client_id"
$clientSecret = "your_client_secret"
$instance = "dev12345"
$tokenUrl = "https://$instance.service-now.com/oauth_token.do"
# Build request body
$body = @{
grant_type = "client_credentials"
client_id = $clientId
client_secret = $clientSecret
}
# Get token
$response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$accessToken = $response.access_token
# Make Table API request
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"
$data = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
$data.result
Notice what's missing compared to the password grant: no username, no password. The script authenticates as the registered application itself, using the Client ID and Client Secret only. The Client Secret is still a credential worth protecting properly — that part of the "avoid hardcoding secrets" advice still applies, and we'll cover secure secret handling in Part 4 — but you're no longer storing an actual human user's password anywhere in the integration at all, which meaningfully reduces what's at risk if the script or its configuration ever leaks.
4. What You Should See
A single incident record, structured in JSON, regardless of which authentication method above you used:
{
"result": [
{
"number": "INC0010001",
"short_description": "Sample Incident",
"state": "1",
"sys_id": "abc123..."
}
]
}
Conclusion
Connecting PowerShell to ServiceNow via the Table API is a powerful step toward automation. Whether you're managing incidents, risks, or CMDB items, understanding authentication methods — and which ones are actually current — is key. Basic Auth is fine for a quick local test; the password grant still works but is on its way out; Client Credentials is the one worth building on for anything you intend to keep running.
In future articles, we'll make this integration enterprise-grade with error handling, secure credential storage, and better performance.
Just tried setting up PowerShell with ServiceNow Table API for my team, and I have to say, this guide made it way easier! I was fumbling around with OAuth tokens and JSON parsing until I ran a quick scenario through customgpt.ai it suggested a clean way to automate the token retrieval and even handle errors gracefully. Now I can pull incident records without worrying about hardcoding creds, and my scripts feel way more production-ready. Big win for anyone trying to make PowerShell + ServiceNow actually work in real life.
ReplyDelete