SN Pro Tips

View Original

Scripted REST APIs & Retrieving RITM Variables via SRAPI

4/5/19: This article has been updated on 4/5/19 to reflect changes to the platform, add more screenshots and clarity, and to add a link to the free, downloadable version of this tool.
11/25/19: This article has been updated to improve the code and handle some edge cases. The tool on the download page has also been updated to version 2.0.

In Fuji and prior releases, ServiceNow has supported the REST API, but they've only supported simple table and record APIs using GET, PUT, POST, PATCH, and so on. In Geneva however, ServiceNow introduced Scripted REST Apis.

See this content in the original post

Scripted REST APIs allow a developer to create a custom REST API Resource, receive request arguments via a REST call, and return data (as with GET requests), create a record (as with POST requests), update records (as with PUT/PATCH requests), or delete records (using a - you guessed it - DELETE request) using custom code that can utilize REST headers, query parameters, and/or request body elements

Scripted REST APIs have only become available fairly recently (in the Geneva release of ServiceNow), and are something that a lot of developers have been avoiding, as they're new and arcane, and the documentation around them is still fairly new, and not very well built-out.
In this article, we're going to learn how to create our own custom scripted REST API, which we'll use for our demo project: Retrieving the service catalog variables associated with a given RITM, for reporting in an external system. 

Pro Tip: If you came here just wanting to deploy this functionality, skip to the bottom of this article, where you'll find information on obtaining a pre-built update set that you can deploy into your instance to enable retrieving catalog item variables via REST!

Before we get started, I want to quickly make clear what is, and is not, available in ServiceNow by default. 
If you've only upgraded to Geneva, there are no scripted REST APIs available by default (except maybe a "user role inheritance" internal API), so you'll pretty much have to write each one yourself. 

However, if you're on Helsinki, there is a "Service Catalog REST API", which allows you to do things like add a catalog item to a cart, update a cart, delete a catalog item from a cart, submit a cart, submit a record producer, and loads more. This is not mentioned in any of the documentation that I've found, and I only learned about it by exploring in my developer instance while writing this article! So if you are just trying to submit catalog items via REST, now you know! There's a way (and a very robust way at that) to do it in Helsinki. 

One thing that's missing, even from the Helsinki scripted REST APIs however, is what we're going to build today -- A simple way to retrieve service catalog variables associated with a given RITM. 


What is REST?

To understand scripted REST APIs, we have to first understand what REST is, and how it's used in ServiceNow. 

I'm not going to go into great depth here about REST, but suffice it to say that REST is a stateless, cacheable "language" that clients and servers can use to talk to one another, and pass data back and forth. You can send a request to a REST resource via an API. REST requests have a few key components:

  • Resource URI: This is the "Unique Resource Identifier". It usually begins with "HTTP://", and it looks like a web address. In fact, it is a web address! If you were to take a simple rest GET request for example, and put it into your browser's URL bar, you would get the results of that request in your browser window!

  • Request Header: This is a set of key-value pairs attached to the request, and is not unlike the header on a webpage. It contains some metadata about the request, such as an authorization token, what "language" (Content-Type) the request is in, and what Content-Type the request will accept a response in.

  • Request Body: The Body of the request is where the bulk of the data can be found. If you're sending a "POST" request for example, which might generate a record on a server, the body of the request might contain the contents of the record to be created.

  • Query Parameters: Query parameters are values added onto the URI of a webpage or, in this case, a REST call. A parameter would look like this:
    http://site.com/api/v1/resource?sys_id=D-1


Similar to how variables work in javascript, request headers, parameters, and the request body can be used to pass data between the client and server. There are a few simple tools that you can use to build REST requests. One of my favorite, is called PostMan for Chrome, and it is free. 

Let's Get Started!

The first thing that we have to do to get started, is navigate to System Web Services -> Scripted Web Services -> Scripted REST APIs, from the Application Navigator.

Right away, you'll notice some significant differences, depending on whether you're in Geneva, or Helsinki or later. In this article, I'm going to be focusing on the Geneva functionality, because it requires more manual work. It should be almost the same, but a smidge easier, in Helsinki. The code will be the same. 

Create the SRAPI

While Helsinki has some Scripted REST APIs already in place, in Geneva, you should be presented with an essentially empty list.
To begin the creation of your REST API, click on New, and fill out a name and API ID. I'm going to use ritm_vars_api (Same as my API name) but you can call yours whatever you like. The API ID will identify your API specifically, and will be part of the API URI. Your API URI will be something like this, when we're through: 
http://your_instance.service-now.com/api/your_company_identifier/API_ID

Save your new Scripted REST Service record, and you'll have 3 new tabs, and 3 related lists. The related lists represent REST resources, headers, and query parameters (described above).

As we build a scripted API to send over the variables and variable values associated with a given request item, we'll need to create a way for the requestor to pass in the RITM ticket numbers they'd like to retrieve the variables for.
We could use query parameters, but let's make use of a request header instead. That just feels more formal to me; you can build your API however you like, so long as you document it! 

Create the REST header

To create a request header, simply select the related list, and click New. The header name is like a variable value, and the user will populate it with the RITM numbers of the tickets they'd like to get the variables for. I created one that looks like this: 

As you can see from the example value, I'm allowing the user to pass in multiple ticket numbers, or just one. The list should be comma-separated. This will make it easier on the requestor if they're generating the API call from a script, because they can just pass an array into the header value and javascript will coerce it into a comma-delimited string in order to conform to the application/json content-type.

And that's pretty much all the data we need from the user for this Scripted REST Service - so let's define our resource. 

Create the REST resource

Back on the Scripted REST Service page, open up the Resources related list, and click New. On this page, we need to define the Http method (get, post, put, etc.), the resource name, and the script that'll do the work for us. 

For the name I entered Get RITM Variables. For the Http Method, I selected GET. In the Documentation section, I entered "This resource returns the variables related to the RITM you've specified.". 

Associate the header to the resource

Now that the Request Header has been created on the Scripted REST API record, and now that we’ve created the Scripted REST Resource record, we need to make sure that the Request Header is associated to the REST Resource as well. This is done from the Request Header Associations related list.

If you don’t already see it here, create a new record that associated the “ritm” Request Header, to the REST resource you created in the previous step.

Write the script

Now all we have to do is define a script which will get the request header, and define the response so that it contains the results that the requestor is looking for. This is the scripted part of Scripted REST APIs. When you create a new resource, you'll be given a script stub that looks something like this: 

See this content in the original post

From this stub, we can tell that we've got access to two parameters that we can make use of, inside the process function: request (a RESTAPIRequest object), and response (a RESTAPIResponse object). If you read our article, What's New in Geneva/UI16, you know that the Geneva script editor is far more powerful now, than it used to be. We can make use of the intellisense style code-completion, to see what methods of the RESTAPIRequest and RESTAPIResponse objects we have access to, by typing "request." or "response." like so:

From this, we can learn a few things about how this all works -- for example, we can use request.getHeader('ritm') to get the value of the RITM header that the user sent along with their request! 

Here's my code for processing these requests: 

See this content in the original post

You can read through the code comments to get a really good sense of what's going on, but basically this script just grabs the value associated with the request header from the request that triggered the REST service to run, then queries the database for the values of the variables associated with the RITMs listed in that header. Once it has them, it returns all the variables and values that have been populated as an object which, in JSON, is returned as the body of the response back to the requestor. Simple! 

Add the Script Include

On line 6 in my REST resource, I make use of a custom script include that I wrote called trimAndSplit(), so here's the code for that as well: 

See this content in the original post

And that's about all there is to it! You can access this API using a tool like the one I mentioned near the beginning of this article, by using a request like this: 

Pro Tip: In the URI next to GET in the above screenshot, the "my_company" bit can be replaced with the API namespace value from your Scripted REST Service page.

If you were to run a request like the one above against an instance that had this scripted REST API enabled, you would get a response that looked something like this:

See this content in the original post

You can download this tool for free, at the link below, where you’ll also find documentation and usage instructions.

Download

Thanks for reading! We put a lot of work into these articles, so if you liked it, we humbly welcome you to subscribe to see more. If your company needs help implementing, enhancing, or building new ServiceNow solutions, we also humbly welcome you to get in touch with us to discuss how we might be able to help you out! 


See this form in the original post

See this content in the original post