CONSUMING SERVICENOW REST API USING PHP

PLEASE SHARE

ServiceNow is one of the widely used ticketing systems in the IT industry.  ServiceNow can be integrated and automated using a rich set of REST API’s available. This article explains how to call ServiceNow REST API’s using PHP. Also, this article can be referenced for how to consume any REST web services using PHP.

We will also explore how to retrieve data from multiple ServiceNow tables that are referenced by or related to each other.

PREREQUISITES

  • ServiceNow developer instance URL with username/password
  • Apache 2 Web Server with PHP 7.3 or above (I am using XAMPP on Windows 10 for this article)
  • Postman tool for exploring the REST API responses

DEMO OPERATIONS

We will demonstrate how to call ServiceNow REST API by implementing the following operations using PHP

  • Retrieve an incident ticket data from the “incident” table (Short Description, Assigned To, and Status). We will also look up the data in tables that are referenced by the incident table such as sys_user and sys_choice.
  • Create a new Incident ticket

GET INCIDENT TICKET DATA

An incident ticket data can be retrieved from the “incident” table by ticket id. Here’s the REST URL for the same,

https://<INSTANCE_ID>.service-now.com/api/now/table/<TABLE_NAME>?sysparm_query=number=<TICKET_ID>&sysparm_limit=1

For Example,

https://dev19250.service-now.com/api/now/table/incident?sysparm_query=number=INC0000002&sysparm_limit=1

Our goal is to retrieve the 3 fields (Short Description, Assigned To, and Status) from an incident ticket.

RETRIEVE SHORT DESCRIPTION

The short description can be read directly from the response of the above REST API. Refer to the Postman screenshot below,

RETRIEVE ASSIGNED USER NAME

The assigned user name is available in the “sys_user” table and it’s referenced from the “incident” table. As we can see below the incident response has a reference link to the “sys_user” table below.

By calling the URL highlighted above, we can get the name of the user assigned to the incident ticket. Please refer below,

Note: In ServiceNow, all the records of a table has a unique ID called “sys_id”. We have an option to get the record using this “sys_id”. Here’s the REST URL for the same,

https://<INSTANCE_ID>.service-now.com/api/now/table/<TABLE_NAME>/<SYS_ID>

RETRIEVE STATUS STRING

As we can see below, the state value is coming as a number in the incident JSON message. We need to get the corresponding label for this value.

We need to look up the “sys_choice” table to get the label string for state numbers. Here’s the REST URL for the same,

https://<INSTANCE_ID>.service-now.com/api/now/table/sys_choice?sysparm_query=name=<TABLE_NAME>^element=<ELEMENT_NAME>^value=<VALUE_NUMBER>

Sample URL,

https://dev19250.service-now.com/api/now/table/sys_choice?sysparm_query=name=incident^element=state^value=2

As shown below, we can get the label string from the response of the above URL,

PHP  CODE TO READ SERVICENOW INCIDENT TICKET DATA USING REST API

Create a PHP file “get_incident_data.php” under XAMPP (For example: C:\xampp\htdocs\php_servicenow_rest_client\get_incident_data.php)

get_incident_data.php

Note: Please read all comment lines in below code to better under the flow and logic

<!DOCTYPE html>
<!--
PHP code to demonstrate how to consume ServiceNow REST API
This PHP code will fetch some data from the ServiceNow incident table such as short_description, assigned_to, and state.
This will also fetch the required data from tables referenced by the incident table such as sys_user and sys_choice.
-->
<html>
	<head>
		<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:ital,wght@0,100;1,300;1,400&display=swap" rel="stylesheet">
		<style>
			body{
					font-family: 'Roboto', sans-serif;
					font-family: 'Roboto Mono', monospace;
			}
		</style>
		<title>ServiveNow REST - Get Incident Details</title>
	</head>
<body>

<h3>SERVICENOW PHP CLIENT - GET INCIDENT DETAILS</h3>
<!-- Form to receive an incident ticket ID from UI -->
<form action="">
	<label for="ticket_id">Ticket ID : </label>
	<input type="text" name="ticket_id" value="<?php echo isset($_GET['ticket_id']) ? $_GET['ticket_id'] : ''?>"/>
	<button type="submit">Get Data</button>
</form>

<?php
	//Specify the ServiceNow developer instance access details
	$servicenow_instance_id = 'dev114830';
	$servicenow_username = 'admin';
	$servicenow_password = 'Bhyg1Lrg2A1QD';

	$servicenow_table_name = 'incident';
	
	if(!empty($_GET['ticket_id'])){
		$ticket_id = $_GET['ticket_id'];
		//Get data from incident table by ticket id
		$response_array = getServiceNowTableData($servicenow_instance_id, $servicenow_username, $servicenow_password, $servicenow_table_name, $ticket_id);

		if(count($response_array['result']) <= 0){
			echo '<p>Ticket ID not found !!!</p>';
		}
		else{
			$short_description = $response_array['result'][0]['short_description'];
			//The assigned to user name is available in the sys_user table which is referenced by the incident table. So we need to use the reference URL for fetching the user name.
			$assigned_to = '';
			if(!empty($response_array['result'][0]['assigned_to'])){
				$assigned_to = callServiceNowRestWebService($response_array['result'][0]['assigned_to']['link'], $servicenow_username, $servicenow_password)['result']['name'];
			}
			
			
			//The incident table has a state number. We need to query the sys_choice table for fetching the label text of the state.
			$status = getChoiceLabel($servicenow_instance_id, $servicenow_username, $servicenow_password, $servicenow_table_name, 'state', $response_array['result'][0]['state']);
?>
			<br>
			<table border='1'>
				<tr>
					<th>Ticket ID</th>
					<td><?php echo $ticket_id;?></td>
				</tr>
				<tr>
					<th>Short Description</th>
					<td><?php echo $short_description;?></td>
				</tr>
				<tr>
					<th>Assigned To</th>
					<td><?php echo $assigned_to;?></td>
				</tr>
				<tr>
					<th>Status</th>
					<td><?php echo $status;?></td>
				</tr>
			</table>
<?php
		}
	}
	
	//Function to get the details from the incident table by ticket id
	function getServiceNowTableData($servicenow_instance_id, $servicenow_username, $servicenow_password, $servicenow_table_name, $ticket_id){
		//Specifying the ServiceNow username & password
		$auth = base64_encode($servicenow_username . ':' . $servicenow_password);
		$context = stream_context_create([
			"http" => [
				"header" => "Authorization: Basic $auth"
			]
		]);

		$rest_api_url = "https://". $servicenow_instance_id .".service-now.com/api/now/table/". $servicenow_table_name ."?sysparm_query=number=". $ticket_id ."&sysparm_limit=1";
		//Call REST Web Service URL. The response will be a JSON string
		$json_response = file_get_contents($rest_api_url, false, $context );
		//Convert JSON string to PHP array
		$response_array = json_decode($json_response, true);
		return $response_array;
	}

	//Function to retrieve the Assigned To username of an incident ticket (From sys_user table)
	function callServiceNowRestWebService($rest_api_url, $servicenow_username, $servicenow_password){
		//Specifying the ServiceNow username & password
		$auth = base64_encode($servicenow_username . ':' . $servicenow_password);
		$context = stream_context_create([
			"http" => [
				"header" => "Authorization: Basic $auth"
			]
		]);
		//Call REST Web Service URL. The response will be a JSON string
		$json_response = file_get_contents($rest_api_url, false, $context );
		//Convert JSON string to PHP array
		$response_array = json_decode($json_response, true);
		return $response_array;
	}
	
	//Function to retrieve the Status label for an incident ticket (from sys_choice table)
	function getChoiceLabel($servicenow_instance_id, $servicenow_username, $servicenow_password, $servicenow_table_name, $element_name, $choice_value){
		//Specifying the ServiceNow username & password
		$auth = base64_encode($servicenow_username . ':' . $servicenow_password);
		$context = stream_context_create([
			"http" => [
				"header" => "Authorization: Basic $auth"
			]
		]);

		$rest_api_url = "https://". $servicenow_instance_id .".service-now.com/api/now/table/sys_choice?sysparm_query=name=" . $servicenow_table_name . "^element=" . $element_name . "^value=" . $choice_value;
		//Call REST Web Service URL. The response will be a JSON string
		$json_response = file_get_contents($rest_api_url, false, $context );
		//Convert JSON string to PHP array
		$response_array = json_decode($json_response, true);
		return $response_array['result'][0]['label'];
		
	}

?>

</body>
</html>

TESTING THE GET INCIDENT DETAILS PHP CODE

Open the URL “http://localhost/php_servicenow_rest_client/get_incident_data.php”,

Enter an incident ticket id,

CREATING NEW INCIDENT TICKET USING REST API

Let’s explore how to create an incident ticket using ServiceNow REST API.

Here’s the REST URL to create an incident ticket,

https://<INSTANCE_ID>.service-now.com/api/now/v1/table/incident

Note: The HTTP method for creating a record should be POST.

The request body should contain the ticket details that we want to create in JSON format. For example,

{
    "short_description": "Memory issue with QA server",
    "category": "hardware",
    "subcategory" : "memory",
    "caller_id": "a8f98bb0eb32010045e1a5115206fe3a",
    "assigned_to" : "71826bf03710200044e0bfc8bcbe5d3b"
}

We can observe from the above JSON request message that we are specifying sys_id’s for caller_id and assigned_to fields since these are having reference to the “sys_user” table. So for creating an incident ticket with users for caller_id and assigned_to fields, first we should get the sys_id of these users. Here’s REST API to get sys_id of a user,

URL:

https://<INSTANCE_ID>.service-now.com/api/now/table/sys_user?sysparm_query=user_name=<USER_NAME>&sysparm_limit=1

Example:

https://dev19250.service-now.com/api/now/table/sys_user?sysparm_query=user_name=aileen.mottern&sysparm_limit=1

Here’s  sample response returning sys_id of a user,

Here’s a sample Postman screenshot demonstrating the creation of incident ticket using REST API,

PHP  CODE TO CREATE SERVICENOW INCIDENT TICKET USING REST API

Create a PHP file “create_incident_ticket.php” under XAMPP (For example: C:\xampp\htdocs\php_servicenow_rest_client\ create_incident_ticket.php)

create_incident_ticket.php

Note: Please read all comment lines in below code to better under the flow and logic

<!DOCTYPE html>
<!--
PHP code to demonstrate how to create a incident ticket with ServiceNow REST API.
This will create the ticket with following data,
1)short_description 2)category 3)subcategory 4)caller_id 5)assigned_to

-->
<html>
	<head>
		<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:ital,wght@0,100;1,300;1,400&display=swap" rel="stylesheet">
		<style>
			body{
					font-family: 'Roboto', sans-serif;
					font-family: 'Roboto Mono', monospace;
			}
		</style>
		<title>ServiveNow REST - Create Incident Ticket</title>
	</head>
<body>

<h3>SERVICENOW PHP CLIENT - Create Incident Ticket</h3>
<!-- Form to receive an incident ticket details from UI -->
<form action="">
	<table>
            <tr>
                <td><label for="short_description">Short Description : </label></td>
                <td><input type="text" name="short_description" value="<?php echo isset($_GET['short_description']) ? $_GET['short_description'] : ''?>"/></td>
            </tr>
            <tr>
                <td><label for="category">Category : </label></td>
                <td><input type="text" name="category" value="<?php echo isset($_GET['category']) ? $_GET['category'] : ''?>"/></td>
            </tr>
            <tr>
                <td><label for="subcategory">Sub Category : </label></td>
                <td><input type="text" name="subcategory" value="<?php echo isset($_GET['subcategory']) ? $_GET['subcategory'] : ''?>"/></td>
            </tr>
            <tr>
                <td><label for="caller_id">Caller User ID: </label></td>
                <td><input type="text" name="caller_id" value="<?php echo isset($_GET['caller_id']) ? $_GET['caller_id'] : ''?>"/></td>
            </tr>
            <tr>
                <td><label for="assigned_to">Assigned to User ID : </label></td>
                <td><input type="text" name="assigned_to" value="<?php echo isset($_GET['assigned_to']) ? $_GET['assigned_to'] : ''?>"/></td>
            </tr>
            <tr>
                <td><button type="submit">Create Ticket</button></td>
            </tr>
    </table>
    
</form>

<?php
	//Specify the ServiceNow developer instance access details
	$servicenow_instance_id = 'dev19250';
	$servicenow_username = 'admin';
	$servicenow_password = 'Weblogic@123';

	$servicenow_table_name = 'incident';
	
	if(!empty($_GET['short_description'])){
        $short_description = $_GET['short_description'];
        $category = $_GET['category'];
        $subcategory = $_GET['subcategory'];
        $caller_id = $_GET['caller_id'];
        $assigned_to = $_GET['assigned_to'];

        //Get sys_id of user fields (from sys_user table)
        $caller_user_sys_id = getSysIDOfUserName($servicenow_instance_id, $servicenow_username, $servicenow_password, $caller_id);
        $assigned_to_user_sys_id = getSysIDOfUserName($servicenow_instance_id, $servicenow_username, $servicenow_password, $assigned_to);

        //Put all incident data in an array
        $incident_data_array = array();
        $incident_data_array["short_description"] = $short_description;
        $incident_data_array["category"] = $category;
        $incident_data_array["subcategory"] = $subcategory;
        $incident_data_array["caller_id"] = $caller_user_sys_id;
        $incident_data_array["assigned_to"] = $assigned_to_user_sys_id;

        $new_incident_number = createIncidentTicket($servicenow_instance_id, $servicenow_username, $servicenow_password, $incident_data_array);
        echo '<p>Incident ticket created successfully. Ticket Id : '. $new_incident_number .'</p>';        
        
        }
    
    //Function to create new incident ticket and return the ID of the same
    function createIncidentTicket($servicenow_instance_id, $servicenow_username, $servicenow_password, $incident_data_array){
        //Specifying the ServiceNow username & password
		$auth = base64_encode($servicenow_username . ':' . $servicenow_password);
		$context = stream_context_create([
			"http" => [
                //since it's a create operation the http method should be POST
                'method'  => 'POST', 
                "header" => array(
                    "Authorization: Basic $auth",
                    "Content-type: application/json"
                ),
                'content' => json_encode($incident_data_array)
			]
        ]);
        
        $rest_api_url = "https://". $servicenow_instance_id .".service-now.com/api/now/v1/table/incident";
        //Call REST Web Service URL. The response will be a JSON string
		$json_response = file_get_contents($rest_api_url, false, $context );
		//Convert JSON string to PHP array
		$response_array = json_decode($json_response, true);
		return $response_array['result']['number'];

    }
	
	//Function to retrieve the sys_id of user_name (from sys_user table)
	function getSysIDOfUserName($servicenow_instance_id, $servicenow_username, $servicenow_password, $user_name){
		//Specifying the ServiceNow username & password
		$auth = base64_encode($servicenow_username . ':' . $servicenow_password);
		$context = stream_context_create([
			"http" => [
                "header" => "Authorization: Basic $auth"
			]
		]);

		$rest_api_url = "https://". $servicenow_instance_id .".service-now.com/api/now/table/sys_user?sysparm_query=user_name=" . $user_name . "&sysparm_limit=1";
		//Call REST Web Service URL. The response will be a JSON string
		$json_response = file_get_contents($rest_api_url, false, $context );
		//Convert JSON string to PHP array
		$response_array = json_decode($json_response, true);
		return $response_array['result'][0]['sys_id'];
		
	}

?>

</body>
</html>

TESTING THE CREATE INCIDENT TICKET PHP CODE

Open the URL “http://localhost/php_servicenow_rest_client/create_incident_ticket.php”,

Enter the incident ticket details below and click on the “Create Ticket” button.

CODE IN GITHUB

The PHP source files of this article are available in the public GitHub repository. Here’s the link for the same,

https://github.com/rajeshkumarraj82/php_servicenow_rest_client

Follow Me

6 Comments

  1. Please, why does this error happen?

    SERVICENOW PHP CLIENT – GET INCIDENT DETAILS
    Fatal error: Uncaught TypeError: Cannot access offset of type string on string in C:\xampp\htdocs\php_servicenow_rest_client\get_incident_data.php:47 Stack trace: #0 {main} thrown in C:\xampp\htdocs\php_servicenow_rest_client\get_incident_data.php on line 47

    1. Hi Jorge, Thank You for reaching out.
      If the “Assigned To” field is empty in the incident ticket, this error can happen. Since the code is not handling this, I added a condition to prevent this. Please copy the latest code of “get_incident_data.php” and try again.
      FYI. I added an if condition at lines number 47, 48
      Please let me know if this resolves your issue. Thank You.

  2. Hi Raj,
    When I send an incident with Postman tool, the record is correct with a lot of attributes (emergency, priority, userId, service, etc).
    When I send an incident with PHP, the record is generated, but only with the following attributes: userId, urgency, description and shortDescription.
    I’m sending with the same values, but in PHP. Do you have any idea why it doesn’t register?
    Thanks a lot!

  3. I didn’t check if your developer instances are still active, but you’ve got the admin passwords for dev19250 and dev114830 listed in the code above and in your github repo.

Leave a Reply

Your email address will not be published. Required fields are marked *

3 + 6 =