How to submit an Order Guide through REST API?

goswami_sudipta
Mega Expert

Hello,

There are OoB REST APIs are available for service catalog, and I wanted to use those to submit an Order Guide. 

My Order Guide consists of two catalog items and can be chosen based on a drop down value in describe needs.The Order Guide is a custom created one which has two OoB items - Standard Laptop (04b7e94b4f7b4200086eeed18110c7fd) and Apple iPad 3 (060f3afa3731300054b6a3549dbe5d3e). Now, when I tried using below REST API Name - Checkout Order guide (https://xxx.service-now.com/sys_ws_operation.do?sys_id=b7fe7ff5c3101200d68d3b0ac3d3aecc).

I am using below values in parameter value and in request body

Path parameters - sys_id : sys_id of the Order Guide

Request Body - 

{"items":[{
  "sys_id":"04b7e94b4f7b4200086eeed18110c7fd",
  "variables":{
    "acrobat":"true",
    "Additional_software_requirements":"MS Office 2007"
  },
  "sysparm_quantity":"3"
}]}

Now when I send this, I am getting below error in response

Status Code: 400 Bad Request

Response body is as below. 

{
  "error": {
    "detail": "",
    "message": "All required items not sent"
  },
  "status": "failure"
}
Could anyone please let me know what I am doing wrong here? Thank you.
8 REPLIES 8

twenger26
Giga Contributor

I am trying to do the same thing.  There seems to be about zero good documentation on submitting Order Guides using the API.   I'm wondering if there is a reason for that...

wakespirit
Kilo Guru

I am trying to do the same thing for submiting an Order from Service Catalog through REST API from a client application.

This is more complicated than just posting request to Request Table but need to hqndle also the possibility to handle choices and dynamic choices based on parent choice selection.

Sounds not easy also, any one have idea best way to go ?

regards

Chris Raga
Tera Expert

I was able to accomplish this through the use of a Scripted REST API and using the OOB functionality for Running Order Guides Automatically.

Essentially I created an endpoint that another application could easily call and trigger the order guide to be submitted. The body for the call is basically composed of:

  • The name of the order guide
  • The User ID of the user the request is for
  • The User ID of the user making the request
  • Any variables that should be set to drive the order guide rule base
{
    "order_guide": "New Setup Order Guide",
    "requested_for": "username1",
    "opened_by": "username2",
    "variables": {
        "onboard_start_date": "2019-01-02",
        "onboard_office_key_requested": true,
        "onboard_travel_expenses_card_requested": true,
        "onboard_voicemail_requested": true,
        "onboard_computer_type_requested": "Desktop",
        "onboard_computer_instructions": "Computer Special Instructions",
        "onboard_facilities_instructions": "Facilities Speical Instructions",
        "onboard_telephone_instructions": "Telephone Special Instructions"
    }
}

My Scripted Rest Resource then reads the body and submits the order guide and provides a response back with the ticket number (Please note this script is a little rough since I only made this as a Proof of Concept):

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
	
	//Set default response variables
	var responseStatus = 200;
	var responseMessage = '';
	var responseDetails = '';
	var responseReqNum = '';
	
	//set the request body to a variable (no need to parse the JSON as ServiceNow does this for us)
	var msg = request.body.data;
	
	//check for mandatory fields
	if (msg != '' && msg.order_guide != "" && msg.order_guide != undefined && msg.requested_for != "" && msg.requested_for != undefined && msg.opened_by != "" && msg.opened_by != undefined){
		
		//attempt to pull sys_id's for mandatory fields
		//set vars to hold the sys_id's
		var orderGuide = "";
		var reqFor = "";
		var openBy = "";
		
		//query for Order Guide
		try{
			var gr_orderGuide = new GlideRecord('sc_cat_item_guide');
			
			//if Order Guide is found, set variable with sys_id
			if(gr_orderGuide.get("name", msg.order_guide)){
				orderGuide = gr_orderGuide.getValue('sys_id');
			}
			//if Order Guide is not found, set response
			else {
				responseStatus = 404;
				responseMessage = "Error";
				responseDetails = "Order Guide: " + msg.order_guide + " could not be found.";
			}
		}
		//set response if query throws an error
		catch(ex){
			responseStatus = 500;
			responseMessage = "Internal Error";
			responseDetails = "Order Guide Query Error: " + ex;
		}
		
		//check to see if Order Guide was found. if so, continue on with processing
		if (orderGuide != ""){
			
			//query for Requested For
			try{
				var gr_reqFor = new GlideRecord('sys_user');
				
				//if Requested For is found, set variable with sys_id
				if(gr_reqFor.get("user_name", msg.requested_for)){
					reqFor = gr_reqFor.getValue('sys_id');
				}
				
				//if Requested For is not found, set response
				else {
					responseStatus = 404;
					responseMessage = "Error";
					responseDetails = "Requested For: " + msg.requested_for + " could not be found.";
				}
			}
			
			//set response if query throws an error
			catch(ex){
				responseStatus = 500;
				responseMessage = "Internal Error";
				responseDetails = "Requested For Query Error: " + ex;
			}
		}
		
		//check to see if Requested For was found. If so, continue with processing
		if (reqFor != ""){
			
			//query for Opened By
			try{
				var gr_openBy = new GlideRecord('sys_user');
				
				//if Opened By is found, set variable with sys_id
				if(gr_openBy.get("user_name", msg.opened_by)){
					openBy = gr_openBy.getValue('sys_id');
				}
				
				//if Opened By is not found, set response
				else {
					responseStatus = 404;
					responseMessage = "Error";
					responseDetails = "Opened By: " + msg.requested_for + " could not be found.";
				}
			}
			
			//set response if query throws an error
			catch(ex){
				responseStatus = 500;
				responseMessage = "Internal Error";
				responseDetails = "Opened By Query Error: " + ex;
			}
		}
		
		//check to see if Opened By was found. If so, finishing processing
		if(openBy != ''){
			
			//start building the JSON for the order guide
			var og_json = {
				"opened_by": openBy,
				"requested_for" : reqFor
			};
			
			//pull variable for the JSON
			for (var property in msg.variables) {
				og_json[property] = msg.variables[property];
			}
			
			//create scriptable order guide
			var sog = new SNC.ScriptableOrderGuide(orderGuide);
			var sog_result = sog.process(new JSON().encode(og_json));
			
			//if the Scriptable Order Guide was submitted successfully (sog_result is a true/false) set response
			if (sog_result){
				var sog_request = sog.getRequest();
				responseMessage = "Success";
				responseDetails = "Order Guide: " + msg.order_guide + " was successfully submitted for: " + msg.requested_for;
				responseReqNum = sog_request.getValue('number');
			}
			
			//if the Scriptable Order Guide was not successful set response
			else {
				responseStatus = 500;
				responseMessage = "Internal Error";
				responseDetails = "Order Guide: " + msg.order_guide + " submission error";
			}
		}
	}
	
	//if mandatory fields are empty
	else {
		responseStatus = 400;
		responseMessage = "Invalid Request";
		responseDetails = "Request is missing one of the following fields: order_guid, requested_for, or opened_by";
	}
	
	//set and return response
	response.setBody({ "message": responseMessage, "details": responseDetails, "req_number": responseReqNum });
	response.setStatus(responseStatus);
		
	})(request, response);

 

Hopefully this helps!

 

This was really very helpful..Thanks...:)