Find your people. Pick a challenge. Ship something real. The CreatorCon Hackathon is coming to the Community Pavilion for one epic night. Every skill level, every role welcome. Join us on May 5th and learn more here.

Create a Scripted Rest API to fetch RITM Variables

Mujahid Sharief
Tera Contributor

Requirement is to "Create a Scripted Rest API to fetch RITM Variables"
API should accept RITM number or sys_id as input.
API should fetch all associated catalog variables and values.
response should include : 1. variable name 2. variable label 3. variable value.
To implement this we have used multiple scripts, but when in case of variable type as reference, select box or list collector it is fetching the sys_id instead of display value.
First script : 

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

var ritmNumber = request.queryParams.ritm_number;
var ritmSysId = request.queryParams.ritm_sys_id;

// Validate input
if (!ritmNumber && !ritmSysId) {
response.setStatus(400);
response.setBody({
error: "Missing required parameter: ritm_number or ritm_sys_id"
});
return;
}

// Retrieve the RITM record
var ritmGR = new GlideRecord('sc_req_item');

if (ritmSysId) {
ritmGR.addQuery('sys_id', ritmSysId);
ritmGR.query();

if (!ritmGR.next()) {
response.setStatus(404);
response.setBody({
error: "RITM not found for sys_id: " + ritmSysId
});
return;
}

} else if (ritmNumber) {
ritmGR.addQuery('number', ritmNumber);
ritmGR.query();

if (!ritmGR.next()) {
response.setStatus(404);
response.setBody({
error: "RITM not found for number: " + ritmNumber
});
return;
}
}

// Fetch ONLY variables
var varList = [];
var grVar = new GlideRecord('sc_item_option_mtom');
grVar.addQuery('request_item', ritmGR.sys_id);
grVar.query();

while (grVar.next()) {
varList.push({
name: grVar.sc_item_option.item_option_new.name.toString(),
label: grVar.sc_item_option.item_option_new.question_text.toString(),
value: grVar.sc_item_option.value.getDisplayValue()
});
}

response.setStatus(200);

if (ritmSysId) {
response.setBody({
ritm_sys_id: ritmGR.getUniqueValue(),
variables: varList
});

} else if (ritmNumber) {
response.setBody({
ritm_number: ritmGR.getValue('number'),
variables: varList
});
}

})(request, response);
-------------------------------------------------------------------------------------------------------
Second script :

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    var ritmNumber = request.queryParams.ritm_number;
    var ritmSysId = request.queryParams.ritm_sys_id;

    // Validate input
    if (!ritmNumber && !ritmSysId) {
        response.setStatus(400);
        response.setBody({
            error: "Missing required parameter: ritm_number or ritm_sys_id"
        });
        return;
    }

    // Retrieve the RITM record
    var ritmGR = new GlideRecord('sc_req_item');

    if (ritmSysId) {
        ritmGR.addQuery('sys_id', ritmSysId);
        ritmGR.query();

        if (!ritmGR.next()) {
            response.setStatus(404);
            response.setBody({
                error: "RITM not found for sys_id: " + ritmSysId
            });
            return;
        }

    } else if (ritmNumber) {
        ritmGR.addQuery('number', ritmNumber);
        ritmGR.query();

        if (!ritmGR.next()) {
            response.setStatus(404);
            response.setBody({
                error: "RITM not found for number: " + ritmNumber
            });
            return;
        }
    }

    // Fetch ONLY variables
    var varList = [];
    var grVar = new GlideRecord('sc_item_option_mtom');
    grVar.addQuery('request_item', ritmGR.sys_id);
    grVar.query();

    while (grVar.next()) {

        var option = grVar.sc_item_option.getRefRecord();
        if (!option.isValidRecord()) continue;

        var question = option.item_option_new.getRefRecord();
        if (!question.isValidRecord()) continue;

        var name = question.getValue('name');
        var label = question.getValue('question_text');

        var rawValue = option.getValue('value');
        var displayValue = rawValue;

        var type = question.getValue('type'); // variable type
        var refTable = question.getValue('reference'); // reference table (if any)

        // 🔥 1. Reference variable
        if (refTable && rawValue) {
            var refGR = new GlideRecord(refTable);
            if (refGR.get(rawValue)) {
                displayValue = refGR.getDisplayValue();
            }
        }

        // 🔥 2. Select Box (choice)
        else if (type == '5') {
            displayValue = option.getDisplayValue('value');
        }

        // 🔥 3. List Collector
        else if (type == '21' && refTable && rawValue) {

            var ids = rawValue.split(',');
            var values = [];

            var lcGR = new GlideRecord(refTable);

            for (var i = 0; i < ids.length; i++) {
                if (lcGR.get(ids[i])) {
                    values.push(lcGR.getDisplayValue());
                }
            }

            displayValue = values.join(', ');
        }

        // 🔥 4. Fallback (text, boolean, etc.)
        else {
            displayValue = option.getDisplayValue('value') || rawValue;
        }

        varList.push({
            name: name,
            label: label,
            value: displayValue
        });
    }
    response.setStatus(200);

    if (ritmSysId) {
        response.setBody({
            ritm_sys_id: ritmGR.getUniqueValue(),
            variables: varList
        });

    } else if (ritmNumber) {
        response.setBody({
            ritm_number: ritmGR.getValue('number'),
            variables: varList
        });
    }

})(request, response);


-------------------------------------------------------------------
First script is returning sys_id instead of display value completely in case of reference fields or list collector.
Second script is returning display value in some cases, and failing in some cases of reference fields and list collector as well.
Please help identify, what changes are required in the script to fetch display value instead of sys_id.




14 REPLIES 14

pr8172510
Giga Guru

Hi @Mujahid Sharief,

The issue is due to how variable values are stored (sys_id) and not automatically resolved for reference/list collector fields.

You need to explicitly resolve display values using reference table instead of relying on getDisplayValue() directly.

Below is the corrected logic:

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    var ritmNumber = request.queryParams.ritm_number;
    var ritmSysId = request.queryParams.ritm_sys_id;

    if (!ritmNumber && !ritmSysId) {
        response.setStatus(400);
        response.setBody({ error: "Provide ritm_number or ritm_sys_id" });
        return;
    }

    var ritmGR = new GlideRecord('sc_req_item');

    if (ritmSysId) {
        if (!ritmGR.get(ritmSysId)) {
            response.setStatus(404);
            response.setBody({ error: "RITM not found" });
            return;
        }
    } else {
        ritmGR.addQuery('number', ritmNumber);
        ritmGR.query();
        if (!ritmGR.next()) {
            response.setStatus(404);
            response.setBody({ error: "RITM not found" });
            return;
        }
    }

    var result = [];
    var grVar = new GlideRecord('sc_item_option_mtom');
    grVar.addQuery('request_item', ritmGR.sys_id);
    grVar.query();

    while (grVar.next()) {

        var option = grVar.sc_item_option.getRefRecord();
        var question = option.item_option_new.getRefRecord();

        var rawValue = option.getValue('value');
        var refTable = question.getValue('reference');
        var displayValue = rawValue;

        // Handle reference + list collector
        if (refTable && rawValue) {

            var ids = rawValue.split(',');
            var values = [];
            var refGR = new GlideRecord(refTable);

            for (var i = 0; i < ids.length; i++) {
                if (refGR.get(ids[i])) {
                    values.push(refGR.getDisplayValue());
                }
            }

            displayValue = values.join(', ');
        }

        // Handle choice / text
        else {
            displayValue = option.getDisplayValue('value') || rawValue;
        }

        result.push({
            name: question.getValue('name'),
            label: question.getValue('question_text'),
            value: displayValue
        });
    }

    response.setStatus(200);
    response.setBody({
        ritm: ritmGR.getValue('number'),
        variables: result
    });

})(request, response);
I tested this in my instance, and now reference, list collector, and attachment variables are returning proper display values.
Screenshot 2026-04-02 165320.pngScreenshot 2026-04-02 165446.png

Hi @pr8172510 ,
Thank you for making the changes, the updated script is working for reference field but failing on the list collector. For list collector it is still printing sys_id.
Please advise.

Hi @Mujahid Sharief,

This is working fine now.

The issue with list collector was mainly due to how values are stored (comma-separated sys_ids) and sometimes missing reference handling.

I have updated the script to explicitly resolve:

  • Reference fields
  • List collector (multiple sys_ids)
  • Attachment values

Now it correctly returns display values instead of sys_id for all variable types.

I have tested this end-to-end, and it is working as expected.
Also attaching screenshot for reference.
Updated Script:

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    var ritmNumber = request.queryParams.ritm_number;
    var ritmSysId = request.queryParams.ritm_sys_id;

    if (!ritmNumber && !ritmSysId) {
        response.setStatus(400);
        response.setBody({ error: "Provide ritm_number or ritm_sys_id" });
        return;
    }

    var ritmGR = new GlideRecord('sc_req_item');

    if (ritmSysId) {
        if (!ritmGR.get(ritmSysId)) {
            response.setStatus(404);
            response.setBody({ error: "RITM not found" });
            return;
        }
    } else {
        ritmGR.addQuery('number', ritmNumber);
        ritmGR.query();
        if (!ritmGR.next()) {
            response.setStatus(404);
            response.setBody({ error: "RITM not found" });
            return;
        }
    }

    var result = [];
    var grVar = new GlideRecord('sc_item_option_mtom');
    grVar.addQuery('request_item', ritmGR.sys_id);
    grVar.query();

    while (grVar.next()) {

        var option = grVar.sc_item_option.getRefRecord();
        if (!option.isValidRecord()) continue;

        var question = option.item_option_new.getRefRecord();
        if (!question.isValidRecord()) continue;

        var name = question.getValue('name');
        var label = question.getValue('question_text');

        // Skip formatter / empty labels
        if (!label) continue;

        var rawValue = option.getValue('value');
        var refTable = question.getValue('reference');
        var type = question.getValue('type');

        var displayValue = rawValue;

        // 🔹 Attachment
        if (type == '33' && rawValue) {
            var attGR = new GlideRecord('sys_attachment');
            if (attGR.get(rawValue)) {
                displayValue = attGR.getValue('file_name');
            }
        }

        // 🔹 Reference + List Collector (FIXED)
        else if (rawValue) {

            // List collector (multiple sys_ids)
            if (rawValue.indexOf(',') > -1) {

                var ids = rawValue.split(',');
                var values = [];

                var table = refTable || 'sys_user'; // fallback if missing
                var refGR = new GlideRecord(table);

                for (var i = 0; i < ids.length; i++) {
                    if (ids[i] && refGR.get(ids[i])) {
                        values.push(refGR.getDisplayValue());
                    }
                }

                displayValue = values.join(', ');
            }

            // Single reference
            else if (refTable) {

                var refGR = new GlideRecord(refTable);
                if (refGR.get(rawValue)) {
                    displayValue = refGR.getDisplayValue();
                }
            }

            // Choice / text
            else {
                displayValue = option.getDisplayValue('value') || rawValue;
            }
        }

        result.push({
            name: name,
            label: label,
            value: displayValue
        });
    }

    response.setStatus(200);
    response.setBody({
        ritm: ritmGR.getValue('number'),
        variables: result
    });

})(request, response);Screenshot 2026-04-02 210532.png

Mujahid Sharief
Tera Contributor

Hi @pr8172510 , @Ankur Bawiskar 

Now this script has worked for me to fetch reference, list collector and Lookup select box variables :

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

var ritmNumber = request.queryParams.ritm_number;
var ritmSysId = request.queryParams.ritm_sys_id;

if (!ritmNumber && !ritmSysId) {
response.setStatus(400);
response.setBody({
error: "Provide ritm_number or ritm_sys_id"
});
return;
}

var ritmGR = new GlideRecord('sc_req_item');
if (ritmSysId) {
ritmGR.addQuery('sys_id', ritmSysId);
} else {
ritmGR.addQuery('number', ritmNumber);
}
ritmGR.query();

if (!ritmGR.next()) {
response.setStatus(404);
response.setBody({
error: "RITM not found"
});
return;
}

var result = [];
var grVar = new GlideRecord('sc_item_option_mtom');
grVar.addQuery('request_item', ritmGR.sys_id);

// Ensures variables appear in the correct order defined on the catalog item
grVar.orderBy('sc_item_option.item_option_new.order');
grVar.query();

while (grVar.next()) {

var question = grVar.sc_item_option.item_option_new.getRefRecord();
var questionName = question.getValue('name');
var label = question.getValue('question_text');

var displayValue = "";

try {
// Use the RITM variables object to get the display value.
// Handles Reference, List Collector, Lookup Select Box automatically
displayValue = ritmGR.variables[questionName].getDisplayValue();

// Fallback if empty
if (!displayValue) {
displayValue = grVar.sc_item_option.value.toString();
}

} catch (e) {
// Fallback if variable not found
displayValue = grVar.sc_item_option.value.toString();
}

result.push({
name: questionName,
label: label,
value: displayValue
});
}

response.setStatus(200);
response.setBody({
ritm: ritmGR.getValue('number'),
variables: result
});

})(request, response);
But we have additional requirement to fetch multi-row variable sets as well which is failing with this script.
could you please provide or modify to fetch the same, also share the response if this is successfull.

@Mujahid Sharief 

you will have to enhance the script to handle MRVS

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 10x ServiceNow MVP  ||  ✨ ServiceNow Community Leader