ServiceNow Scripted REST APIs
Scripted REST APIs let developers build custom API endpoints inside ServiceNow. While the built-in Table API reads and writes standard table data, Scripted REST APIs expose custom business logic — combining data from multiple tables, applying complex transformations, enforcing business rules, and returning exactly the format an external system needs. They are the foundation of sophisticated integrations.
Built-in Table API vs. Scripted REST API
TABLE API SCRIPTED REST API ────────────────────────────────────────────────────────── Fixed behavior Custom logic you write Returns raw table data Returns any format you design No business logic Full JavaScript control No data transformation Combine, filter, transform freely One table at a time Join multiple tables in one call External systems cannot External systems get exactly customize the format what they need
Creating a Scripted REST API
Navigate to System Web Services > Scripted REST APIs and click New. Fill in:
- Name: A descriptive name for the API (e.g., "Incident Summary API")
- API ID: The URL path segment (e.g., "incident_summary")
- API version: v1 by default — versioning supports future changes without breaking existing callers
After saving the API, open its record and add Resources — the individual endpoints within this API.
Resources: Individual Endpoints
A resource is one specific URL path + HTTP method combination. One Scripted REST API can contain multiple resources handling different operations.
Scripted REST API: "Incident Summary API"
Base path: /api/x_acme/incident_summary
Resources:
GET /api/x_acme/incident_summary/open → Return open incident count
GET /api/x_acme/incident_summary/{number} → Return one incident summary
POST /api/x_acme/incident_summary/create → Create incident + notify
DELETE /api/x_acme/incident_summary/{sys_id} → Close and archive incident
Path Parameters
Curly braces in a resource path define path parameters — variable segments that the caller fills in. The script accesses them through the request object.
Resource path: /api/x_acme/incident_summary/{number}
Caller hits: .../incident_summary/INC0001234
Script access:
(function process(request, response) {
var incNumber = request.pathParams.number; // "INC0001234"
// ... fetch and return that specific incident
})(request, response);
The Resource Script
Each resource has a script that runs when the endpoint is called. The script receives two objects — request (the incoming call) and response (what to send back). The script reads input, performs logic, and writes the response.
(function process(request, response) {
// Read a query parameter from the URL
var groupFilter = request.queryParams.group || '';
// Build the response data
var agg = new GlideAggregate('incident');
agg.addQuery('state', 'NOT IN', '6,7');
if (groupFilter) {
agg.addQuery('assignment_group.name', groupFilter);
}
agg.addAggregate('COUNT');
agg.query();
var count = 0;
if (agg.next()) {
count = parseInt(agg.getAggregate('COUNT'));
}
// Set HTTP status and return JSON
response.setStatus(200);
response.setContentType('application/json');
response.setBody({
group: groupFilter || 'all',
open_incident_count: count,
retrieved_at: new GlideDateTime().getDisplayValue()
});
})(request, response);
Reading Request Data
The request object provides access to all incoming data:
- request.pathParams.paramName — Path parameter values from the URL
- request.queryParams.paramName — Query string parameters after the ?
- request.body.data — The JSON body of a POST or PATCH request (parsed automatically)
- request.headers.get('header-name') — HTTP request headers
Setting HTTP Response Status Codes
REST APIs communicate success and failure through HTTP status codes. Always set the appropriate code explicitly:
- 200 OK — Request succeeded, data returned
- 201 Created — New record created successfully
- 400 Bad Request — Caller sent invalid data
- 401 Unauthorized — Authentication failed
- 404 Not Found — Requested record does not exist
- 500 Internal Server Error — Script error on the server
API Versioning
ServiceNow Scripted REST APIs support multiple versions. When an external system depends on a specific API response format, releasing a new version (v2) preserves the old v1 endpoint untouched. External systems migrate to v2 on their own schedule. This prevents breaking changes from disrupting integrations — a critical requirement in enterprise environments with dozens of connected systems.
Security: ACL Protection on Scripted REST APIs
Scripted REST API endpoints respect ServiceNow's ACL security model. Unauthenticated callers receive a 401 error. Authenticated callers only access the data their roles permit. Administrators add explicit REST API access controls at the resource level for additional protection beyond the standard table-level ACLs.
