ServiceNow exposes a comprehensive REST API surface that covers almost everything you can do through the UI. This reference covers the APIs you will actually use in production integrations, not just the basics.
Table API — The Foundation
The Table API lets you query, create, update, and delete records in any ServiceNow table. The base URL pattern is:
https://<instance>.service-now.com/api/now/table/<table_name>
Query Parameters
The Table API supports a rich set of query parameters that map directly to GlideRecord operations:
// Get active P1 incidents, return only key fields
GET /api/now/table/incident
?sysparm_query=active=true^priority=1
&sysparm_fields=number,short_description,assigned_to,state
&sysparm_limit=100
&sysparm_offset=0
&sysparm_display_value=true
Key parameters:
sysparm_query— encoded query string (same syntax as GlideRecord)sysparm_fields— comma-separated list of fields to returnsysparm_display_value— true returns display values, false returns raw values, all returns bothsysparm_limit— max records per page (max 10,000)sysparm_offset— pagination offsetsysparm_exclude_reference_link— true removes the link objects from reference fields, reducing payload size
Authentication
Basic Authentication
Simplest to implement, appropriate for server-to-server integrations in controlled environments:
Authorization: Basic <base64(username:password)>
Never use Basic Auth with a named user account. Always create a dedicated integration user with only the roles needed for that integration.
OAuth 2.0 — Client Credentials
The recommended approach for server-to-server integrations:
// Step 1: Get access token
POST /oauth_token.do
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&username=<integration_user>
&password=<integration_user_password>
// Response
{
"access_token": "abc123...",
"token_type": "Bearer",
"expires_in": 1800
}
// Step 2: Use the token
GET /api/now/table/incident
Authorization: Bearer abc123...
Scripted REST APIs
When the Table API does not fit your use case — for example, you need to expose a custom business operation or aggregate data from multiple tables — Scripted REST APIs let you build custom endpoints on the ServiceNow platform.
// Example: Custom endpoint that returns incident metrics
(function process(request, response) {
var ga = new GlideAggregate('incident');
ga.addEncodedQuery('active=true');
ga.addAggregate('COUNT', 'priority');
ga.groupBy('priority');
ga.query();
var metrics = {};
while (ga.next()) {
metrics[ga.priority.getDisplayValue()] =
ga.getAggregate('COUNT', 'priority');
}
response.setStatus(200);
response.setContentType('application/json');
response.setBody(JSON.stringify(metrics));
})(request, response);
Pagination Pattern
The Table API returns a maximum of 10,000 records per request. For large datasets, implement proper pagination:
// Check response headers for total count
X-Total-Count: 45823
// Paginate using offset
GET /api/now/table/incident?sysparm_limit=1000&sysparm_offset=0
GET /api/now/table/incident?sysparm_limit=1000&sysparm_offset=1000
GET /api/now/table/incident?sysparm_limit=1000&sysparm_offset=2000
// ... continue until offset >= X-Total-Count
Batch API
The Batch API allows multiple REST calls in a single HTTP request, significantly reducing round-trip overhead for operations that require several sequential API calls:
POST /api/now/v1/batch
{
"batch_request_id": "batch_001",
"rest_requests": [
{
"id": "create_incident",
"method": "POST",
"url": "/api/now/table/incident",
"body": { "short_description": "Test", "category": "software" }
},
{
"id": "get_user",
"method": "GET",
"url": "/api/now/table/sys_user?sysparm_query=user_name=john.smith"
}
]
}
Error Handling
The Table API returns standard HTTP status codes. Your integration must handle:
401— Authentication failed or token expired. Refresh the token and retry.403— Insufficient permissions. Check the integration user's roles.404— Record or table not found. Verify the sys_id and table name.429— Rate limit exceeded. Implement exponential backoff.500— Server error. Log and alert — do not retry automatically.
Performance Tips
- Always specify
sysparm_fields— never return all fields if you only need three - Use
sysparm_exclude_reference_link=trueto cut response size significantly - Cache access tokens until they expire rather than fetching a new one per request
- Use the Batch API when you need 3 or more sequential calls
- Compress large request bodies with gzip when the endpoint supports it