top of page

Transforming a Processor into a Scripted REST API in ServiceNow

  • Writer: Paul Nguyen
    Paul Nguyen
  • 4 days ago
  • 5 min read

If you’ve been working in the ServiceNow ecosystem for a while, you probably have a few legacy Processors in your instance. For years, Processors were the go-to way to create custom API endpoints to handle external data integration into ServiceNow or return specific data formats like JSON or XML.


ServiceNow has officially deprecated Processors so you can no longer create new processors and instead recommends you now use Scripted REST APIs. Your current processors will still continue to work for the time being.


From our perspective, we wanted to transform our Processors into Scripted REST APIs considering that Processors are being deprecated (so they will eventually stop working) and so we could take advantage of features in Scripted REST APIs as well as use a feature that's currently being actively supported.


So if you've been putting off migrating your old processors because "they still work," this guide is for you.



Why Convert a Processor to a Scripted REST API?


There are several reasons to convert a processor into a scripted REST API:


  • Proper HTTP Method Handling: Processors often forced you to handle GET, POST, PUT, and DELETE requests together inside a single script. Scripted REST APIs allow you to define and handle each HTTP method separately.

  • Security: Scripted REST APIs integrate seamlessly with ServiceNow's robust standard authentication (OAuth 2.0, Basic Auth) and ACLs.

  • Automatic Content Negotiation: Scripted REST APIs automatically parse incoming JSON or XML into neat JavaScript objects (request.body.data).

  • API Versioning: You can version your endpoints (e.g., /v1/myservice, /v2/myservice) out of the box, ensuring you don't break external integrations when making updates.

The Migration Blueprint: From Processor to Scripted REST API


Let’s look at a scenario where you call a legacy multi-table Processor to return some information about a table, such as its label and record count.


  1. The Legacy Processor (What We're Replacing)

var table = g_target;

if (!table) {
    g_processor.writeOutput("application/json", JSON.stringify({
        error: "No target table."
    }, null, 2));
    return;
}

var result = {
    table: table
};

var gr = new GlideRecord(table);

if (!gr.isValid()) {
    result.error = "Invalid table";
    g_processor.writeOutput("application/json", JSON.stringify(result, null, 2));
    return;
}

result.canRead = gr.canRead();

// Record count
var agg = new GlideAggregate(table);
agg.addAggregate("COUNT");
agg.query();
if (agg.next())
    result.recordCount = agg.getAggregate("COUNT");

// Table label
result.label = gr.getClassDisplayValue();

g_processor.writeOutput("application/json", JSON.stringify(result, null, 2));

How our Processor example looks like as a record in ServiceNow:

Processor Example
Processor Example

With this multi-table Processor, you use the TABLE_INFO parameter when called against a table. For example, if you want to call it against the incident table, you call https://<instancename>.service-now.com/incident.do?TABLE_INFO


And then in your Processor script, you would access the table the Processor is called against by using g_target and then g_processor and g_response to write out a response to the API request. See Processor API Components for all the different objects and methods available.


  1. The New Scripted REST API Solution

To recreate the Prcoessor as as Scripted REST API, we break the logic into two parts: the API Record (the container) and the Resource Record (the specific endpoint action).


Step A: Create the Scripted REST API Service

  1. Navigate to System Web Services > Scripted Web Services > Scripted REST APIs.

  2. Click New.

  3. Name your service (e.g., Table Info) and give it an API ID (e.g., table_info).

  4. Select ACLs to use for the Default ACLs (such as Scripted REST External Default, which is an ACL included in your instance by default that you can use).

  5. Save the record. This establishes your base path: /api/x_your_scope/table_info. See the Scripted REST API documentation for more info on the different configurations as well as examples. How our Scripted REST Service example looks like as a record in ServiceNow:

    Scripted REST Service Example
    Scripted REST Service Example

Step B: Create the Resource (The GET Method)

  1. In the Resources related list of your new API record, click New.

  2. Configure the resource:

    • Name: Get Table Info

    • HTTP Method: GET

    • Relative Path: /details (This makes the full URL /api/x_your_scope/table_info/details)

  3. Scroll down to the Script block. With a Scripted REST API, you can use the RESTAPIRequest and RESTAPIResponse APIs/objects to get all info about the incoming API request and foryour response back. So you can copy your code from your processor and then will need to change how you access the request and its parameters along with how your respond back to the API request. In our example, we will now use a query parameter named table to pass in the table name i.e. /api/x_your_scope/table_info/details?table=incident, accessing it from the RESTAPIRequest and its queryParams object. This replaces using the g_target object in the Processor. For the response, we can actually just return the desired result (the JSON object) as a return to the script function. The resulting script block would be:

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    var queryParams = request.queryParams;
    var table = queryParams.table;

    if (!table) {
        response.setStatus(400);
        return {
            error: "Table name is required."
        };
    }

    var gr = new GlideRecord(table);

    if (!gr.isValid()) {
        response.setStatus(404);
        return {
            error: "Invalid table: " + table
        };
    }

    var result = {
        table: table,
        canRead: gr.canRead()
    };

    // Table label
    result.label = gr.getClassDisplayValue();

    // Record count
    var agg = new GlideAggregate(table);
    agg.addAggregate("COUNT");
    agg.query();

    if (agg.next())
        result.recordCount = parseInt(agg.getAggregate("COUNT"), 10);

    return result;

})(request, response);

Notice how much cleaner the API is when you use the modern request and response objects. The parts in bold are what we changed since we access the request and response differently from how we were doing it in a Processor. Otherwise the rest of the code can be re-used from the Processor.


How our Scripted REST Resource example looks like as a record in ServiceNow:

Scripted REST Resource Example
Scripted REST Resource Example

Note we can also use the RESTAPIResponse object to directly write the response back i.e.

	response.setContentType("application/json");
	response.setStatus(200);
	var writer = response.getStreamWriter();
	writer.writeString(result);

  1. Next Steps


Now that you've created your Scripted REST API, do all the necessary steps in your software development lifecycle and deployment process so your external systems and integrations can use the new Scripted REST API.


This includes testing the API (such as using the REST Explorer), securing the API with proper authentication and updating your external systems and integrations to use the new API, keeping the Processor as a fallback option until all systems and integrations are using the new Scripted REST API.


One thing that may be useful is to extract reusable functions to Script Includes and call the Script Includes from the script block of your Scripted REST Resources. This way you're not writing all the code in the Scripted REST Resource (or previously the Processor) and it becomes easier to maintain since you can update the Script Include in the future when you need to make changes as well as use it elsewhere in our instance (business rules, scheduled jobs, etc).


For example, using the script from the Scripted REST Resource above, we can update it to reference a Script Include named TableData instead:

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    var queryParams = request.queryParams;
    var table = queryParams.table;

    var tableGr = new TableData();
    return tableGr.getInfo(table);
    
})(request, response);

Wrap Up


Migrating away from legacy Processors isn't just a matter of technical debt compliance and moving away from deprecated functionality. Scripted REST APIs give you better error handling, cleaner code structure as well as native security controls and are the path going forward for building APIs into ServiceNow.


And it's really not as difficult to migrate as we've done here. Feel free to reach out to me if you want to discuss this or anything else further.


Saiborne offers software consulting services to help companies meet their business objectives and get the most value out of their software products. We specialize in ServiceNow solutions with our certified experience including development of apps released to the ServiceNow Store with our previous companies. Contact us to find out how we can help you with any ServiceNow needs.



bottom of page