Creating Webhooks in ServiceNow

How to automate sending data from ServiceNow with Business Rules

Taylor Barnett
May 17th, 2021
Share

Gone are the days where data is housed within one system are long gone. Now, up-to-date ticket data is often needed in other systems outside of ServiceNow, not just ServiceNow. However, making this happen without writing a lot of code can be quite tricky. I recently found a way to replicate webhook-like behavior using the ServiceNow built-in REST client alongside Business Rules. Previously, I have raved about the importance of webhooks in data integrations, which seemed like an excellent possible solution for the problem. The ability to have real-time data coming out of ServiceNow can enable teams to use the data more efficiently and integrate it into existing workflows.

In this blog post, I will break down how I set this up in my ServiceNow instance so you can have outgoing webhooks from ServiceNow to whatever target you choose. For example, when an incident is created in ServiceNow, the data is automatically sent to my webhook target to use the data to enrich other systems.

ServiceNow Business Rules

But first, what are Business Rules? Business Rules are based on ServiceNow server-side logic that executes when database records are inserted, updated, queried, or deleted. So, for example, if someone creates a ticket in the Incident table in ServiceNow, you can set up a business rule to run.

ServiceNow’s RESTMessageV2 API

Another feature of Business Rules is that you can use it to trigger custom scripts. This is where the REST client comes in. The ServiceNow RESTMessageV2 API is essentially a REST client that allows you to send outbound REST messages using JavaScript. In your head, alarm bells should be going off because that’s basically like creating a webhook— just what we wanted!

The RESTMessageV2 API allows us to access the ticket (or record) data that triggered the business rule and put it in the body of the outgoing REST POST request to send to your chosen webhook target URL.

How to set it up

I’m going to walk you through a basic example of using this strategy. As always, your data model might not match this exact example. I used the default incident table with no customization, but you should get the idea of how to create your webhook-like functionality with the following:

  1. In your ServiceNow instance, go to System Definition > Business Rules.
  2. Select New.
  3. Give your new Business Rule a descriptive name, choose what table you want it to trigger on, and check the Advanced box.
  4. Next, choose After for when you want it to run. I am choosing after because often, you want the data to send after it has been inserted, updated, or deleted. Doing it before the transaction is complete could lead to inaccurate data. You may also choose to add filter conditions, but we want it to trigger for all incident tickets in this example. Also, for this example, we want to select Insert because we want it to trigger when a new incident ticket is created.
  5. Lastly, navigate to the Advanced tab. In the Script editor, add the following code. Make sure to replace <insert webhook public URL> with whatever the webhook target is. The target URL may be a web server that will parse and use the data or another service that accepts incoming webhooks, like Transposit.
(function executeRule(current, previous /*null when async*/ ) {
 try {
 var r = new sn_ws.RESTMessageV2();
 r.setEndpoint("<insert webhook public URL>");
 r.setHttpMethod("post");

 // getValue(string) does not support dot walking, 
 // so I had to do a bit more to get the user’s email address
 var usr = new GlideRecord('sys_user');
 usr.get('sys_id', current.getValue("caller_id"));
 var reported_by_email = usr.getValue('email');

 // Make sure to convert object references to values.
 // More info at: 
 // https://swissbytes.blogspot.com/2017/11/service-now-script-includes-make-sure.html

 var number = current.getValue("number");		
 var opened_at = current.getValue("opened_at");
 var impact = current.getValue("impact");
 var urgency = current.getValue("urgency");
 var short_description = current.getValue("short_description");
 var description = current.getValue("description");
 var category = current.getValue("category");
 var priority = current.getValue("priority");
 var sys_id = current.getValue("sys_id");
 var subcategory = current.getValue("subcategory");
 var state = current.getValue("state");

 var obj = {
 "number": number,
 "reported_by_email": reported_by_email,
 "opened_at": opened_at,
 "impact": impact,
 "urgency": urgency,
 "short_description": short_description,
 "description": description,
 "category": category,
 "priority": priority,
 "sys_id": sys_id,
			"subcategory": subcategory,
			"state": state
 };
		
 var body = JSON.stringify(obj);
 gs.info("Webhook body: " + body);
 r.setRequestBody(body);

 var response = r.execute();
 var httpStatus = response.getStatusCode();
 } catch (ex) {
 var message = ex.message;
		gs.error("Error message: " + message);
 }

 gs.info("Webhook target HTTP status response: " + httpStatus);

})(current, previous);

If you have a custom table and fields, you might need to make modifications. I only wanted specific fields sent with our webhook in my use case, so I specified them in the code. Also, I wanted fields to be instantly valuable to the external system. For example, I am getting the email address of who created the ticket instead of their sys_id because that id doesn’t mean much to my external system and would cause me to make a second API call to get more information.

If you want all of the data, you may also choose to loop through your GlideRecord and pull out the fields and elements to send all the fields for your ticket, but this would make it harder to dot walk to get more information, like emails.

Testing

Finally, once you have set up the webhook, you can test the business rule based on the triggering conditions. Make sure to check the response body for the data being sent from ServiceNow. If you are using another service, they often have a way to look at incoming requests or log out the response body if you have access to the server yourself.

I added some logging to the script, but you might need to add more gs.log() statements in the code to see what is going on in your System Logs. One thing to watch out for is that the web server the webhook is being sent to responds with a 200 status code. Otherwise, there might be an issue with the target and not the webhook itself.

So the next time you need data from ServiceNow to automatically send to other systems, you can use Business Rules using the RESTMessageV2 API to create your own webhooks.

Share