How to Send a Custom Response to Table API?

aen612
Tera Guru

Hello,


I'm wondering, if possible, how to provide a custom response to a table api, specifically /api/now/v2/table/incident.

Ultimately, for a specific integration user, we don't actually want them to create an incident but instead create a service_task. This is for a pre-configured 3rd party integration and the ServiceNow endpoint the 3rd party app is calling is not configurable.

I've created a before insert business rule on incident, and am preventing the creation of the incident and creating the service_task. I'd like to send the created service_task number in the response back to the 3rd party app. Ideally, I'd intercept the incoming call before the incident table is even hit.

Anyone have any ideas?


Here's the BR I've created, not sure if that's helpful or not.

 

(function executeRule(current, previous /*null when async*/ ) {
    // Add your code here
    if (gs.getUserName() == 'testIntegrationUser') {
        var sTask = new GlideRecord('service_task');
        sTask.initialize();
        sTask.opened_by = current.opened_by;
        sTask.assignment_group = current.assignment_group;
        sTask.assigned_to = current.assigned_to;
        sTask.short_description = current.short_description;
        sTask.description = current.description;
        sTask.insert();
        current.setAbortAction(true);
        return sTask;        
    }
})(current, previous);

 


Current response:

 

{
    "error": {
        "message": "Operation Failed",
        "detail": "Operation against file 'incident' was aborted by Business Rule 'testBR_Insert^80753607db22551042a55716f4961935'. Business Rule Stack:testBR_Insert"
    },
    "status": "failure"
}

 


Also, does anyone know how/where to see the responses sent back to an inbound REST call? I can find the incoming call, etc. using Node Log File Browser, but not seeing the actual response being sent, just seeing similar to below:

 

Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] TableAPIService : Creating service result for insert request
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] ServiceHandler : End of Service Invocation TableAPIV2Service
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] ServiceHandler : Service Invocation Duration duration_micro_secs=187801
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] ServiceResultHandler : Serializing Response
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] ServiceResultHandler : End of Response Serialization
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] ServiceResultHandler : Response Serialization Duration duration_micro_secs=502
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] RESTAPIProcessor : Service handling duration duration_micro_secs=188449
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] RESTAPIProcessor : End of Request Processing
Debug	API_INT-thread-1	txid=1ae36576dbea DEBUG: #30806 [REST API] RESTAPIProcessor : REST Request Processing time total_time_to_now_micro_secs=209605
Info	API_INT-thread-1	txid=1ae36576dbea tx_pattern_hash=106512468 *** End #30806 /api/now/v2/table/incident, user: testIntegrationUser, total time: 0:00:00.211, processing time: 0:00:00.211, CPU time: 0:00:00.164, SQL time: 0:00:00.043 (count: 98), business rule: 0:00:00.074 (count: 37), ACL time: 0:00:00.031, Script time: 0:00:00.107 (count: 93), source: 52.2.37.56, type: rest , method:POST, api_name:now/table, resource:now/v2/table/incident, version:v2, user_id:021795321ba21594d50c5460604bcbf1, response_status:201

 

Thanks!
Aaron

4 REPLIES 4

Tony Chatfield1
Kilo Patron

Hi, I'm not sure that a before BR is the best approach for your solution. If you are wanting to create multiple task types from the 1 end point and\or manage field mapping then I would consider a scripted rest API from a single task type end point. This would allow you to populate into appropriate task table, return a custom response and set table specific fields\values in a before transform script.

Unfortunately we’re not able to configure the 3rd party app to send to a different endpoint, it’s hard coded to send to /api/now/v2/table/incident. If we could update that app it would make things way more simple and clean. 🙂

With careful field mapping and a script to get the correct task number, you could probably update the sys_class_name\task type in your before BR rather than using a gliderecord insert and abort (I haven't tested). But would need to test\validate the impact and I am not sure if I would call the solution best practice - as well as a functional solution you need to consider the technical debt that this type of workaround incurs.

Thanks for the suggestion!

I've just now tried setting current.sys_class_name = 'service_task' in the before BR and still an incident is created (well, task number begins with INC), however it's created in the service_task table. Progress, maybe?! I should be able to look up the next available service_task number, etc. and get the service_task created, but still I think where I'll get stuck is returning the service_task number, as the incident number is logged before my BR is run. 

Here's what I have in the BR:

 

(function executeRule(current, previous /*null when async*/ ) {
    // Add your code here
    if (gs.getUserName() == 'testIntegrationUser') {
		current.sys_class_name = 'service_task';
    }
})(current, previous);

 


Snippet of debug from Postman:

 

                "params": {
                    "record_display": "INC0040722",
                    "when_engines": "after engines (order >=1000)",
                    "when": "after",
                    "operation": "insert",
                    "table": "service_task"
                },

 


And from Session Log:

 

09:06:14 AM.605 Global ==> 'testBR_Insert' on incident: INC0040722
09:06:14 AM.606 Ran in 479 microseconds script: '(function executeRule(current, previous /*null when async*/ ) { // Add your code here if (gs.getUserName() == 'testIntegrationUser') { current.sys_class_name = 'service_task';} })(current, previous);'
09:06:14 AM.607 Global           sys_class_name: incident => service_task
09:06:14 AM.607 Global <== 'testBR_Insert' on incident: INC0040722

 


Regarding best practices and technical debt, I understand that what we're trying to accomplish is less than ideal. Ideally (well aside from using the correct endpoint in the first place :)) we'd intercept the incoming REST call before the incident table is even 'touched'.

Looking at Session Log Debug, the first step is 'RESTAPIProcessor', then some ACL evaluations, then right to: 'Processing REST Request /api/now/table/incident'. Is RESTAPIProcessor something that we have access to? I've not been able to locate it.

Ultimately, I think I've talked myself out of trying to get this to work with a before BR on incident. Too many things are happening as a result of the initial endpoint '/api/now/table/incident', Incident SLA rules, Major Incident stuff, etc.