Make Client-Side API Calls for Catalog Item Population
Master the CSA-approved pattern for securely populating Service Catalog fields with external API data using Client Scripts, GlideAjax, Script Includes, and RESTMessageV2.
The "Real-Time" Integration Challenge
You're building a Service Catalog Item and need to populate a dropdown, lookup field, or text input with data from an external system – before the user even hits "Submit." Perhaps it's a list of available servers from Azure, current stock levels from an ERP, or customer data from Salesforce.
This is a common requirement, but it immediately poses a challenge: How do you securely and efficiently make an external API call from a client-side Catalog Item? And more importantly, what's the ServiceNow CSA-approved best practice that won't compromise your instance's performance or security?
Many new admins try to force a server-side solution or, worse, attempt direct client-side scripting to external APIs (a huge no-no!). Let's break down the correct, maintainable, and exam-friendly approach.
Why Server-Side Tools (Like Flow Designer/IntegrationHub) Fall Short HERE
First, let's address what won't work directly for client-side population:
Flow Designer / IntegrationHub
These are powerful tools for server-side automation (i.e., after a record is submitted, updated, or an event occurs). They run asynchronously and have no direct access to the client-side form to dynamically update variables in real-time as the user interacts.
Business Rules
These also run on the server (before/after insert/update/delete) and cannot directly manipulate client-side form variables in real-time.
For data needed before submission, you need a client-side trigger that securely delegates the heavy lifting to the server.
The CSA Best Practice: Client Script + GlideAjax + Script Include + RESTMessageV2
This is the tried-and-true pattern for securely fetching data from external APIs and populating Catalog Item variables dynamically on the client-side. Each component plays a vital role:
1. The Trigger: Catalog Client Script
Role: This script runs in the user's browser, reacting to form events. It initiates the request for data.
Best Practice:
- Typically
onLoad(to populate when the form loads) oronChange(to populate based on another variable's selection). - Uses standard
g_formmethods (e.g.,g_form.getValue()) to get existing data andg_form.setValue()to set returned data. - Crucially, it uses GlideAjax to send the request securely to the server.
2. The Secure Bridge: GlideAjax
Role: GlideAjax is the essential, secure communication channel between your client-side Catalog Client Script and a server-side Script Include. It prevents direct client-side access to server-side APIs or credentials.
Best Practice:
- Always use asynchronous calls (
getXMLWait()is generally discouraged due to UI blocking). - Pass necessary parameters (e.g., the value of another variable) to the Script Include.
3. The API Orchestrator: Client-Callable Script Include
Role: This is where the secure, server-side logic resides. It receives the request from GlideAjax, builds the external API call, and processes the response.
Best Practice:
- Must be marked Client callable (
gs.isLoggedIn()check is always a good idea). - Defines a function that extends
global.AbstractAjaxProcessor. - Retrieves parameters using
this.getParameter('sysparm_...'). - This is where you instantiate and execute RESTMessageV2.
4. The External Communicator: RESTMessageV2
Role: Within your Script Include, RESTMessageV2 (or its scoped counterpart) is the class specifically designed to make outbound RESTful API calls from the ServiceNow server.
Best Practice:
- Always define your REST Message in System Web Services > Outbound > REST Message first. This stores the endpoint, authentication, and HTTP methods securely.
- Call the defined REST Message from your Script Include. This keeps credentials out of the code.
- Properly handle response codes and potential errors.
Step-by-Step Flow for the CSA Exam:
- User loads/interacts with Catalog Item.
- Catalog Client Script triggers, creates a GlideAjax object.
- GlideAjax sends parameters to a Client-Callable Script Include.
- Script Include receives parameters, builds the RESTMessageV2 call.
- RESTMessageV2 makes a secure API call to the external system.
- External system responds.
- Script Include parses the response.
- GlideAjax receives the processed data back.
- Catalog Client Script updates the Catalog Item variables based on the data.
Implementation Example
Step 1: Create the REST Message
Navigate to System Web Services > Outbound > REST Message
- Name: Azure Servers API
- Endpoint: https://api.azure.com/servers
- Authentication: OAuth 2.0 or Basic Auth
- HTTP Method: GET
Step 2: Create the Client-Callable Script Include
var AzureServerFetcher = Class.create();
AzureServerFetcher.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
getServers: function() {
// Verify user is logged in
if (!gs.isLoggedIn()) {
return JSON.stringify({error: 'Unauthorized'});
}
// Get parameters from client
var region = this.getParameter('sysparm_region');
try {
// Call the REST Message
var request = new sn_ws.RESTMessageV2('Azure Servers API', 'GET');
request.setQueryParameter('region', region);
var response = request.execute();
var httpStatus = response.getStatusCode();
if (httpStatus == 200) {
var responseBody = response.getBody();
var servers = JSON.parse(responseBody);
return JSON.stringify(servers);
} else {
return JSON.stringify({error: 'API returned status ' + httpStatus});
}
} catch (ex) {
gs.error('Error fetching servers: ' + ex.message);
return JSON.stringify({error: 'Failed to fetch servers'});
}
},
type: 'AzureServerFetcher'
});
Important: Check the Client callable checkbox in the Script Include record!
Step 3: Create the Catalog Client Script
Type: onChange
Variable name: region (the variable that triggers the fetch)
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue === '') {
return;
}
// Show loading indicator
g_form.showFieldMsg('server', 'Loading servers...', 'info', true);
// Create GlideAjax object
var ga = new GlideAjax('AzureServerFetcher');
ga.addParam('sysparm_name', 'getServers');
ga.addParam('sysparm_region', newValue);
// Make asynchronous call
ga.getXMLAnswer(function(response) {
try {
var data = JSON.parse(response);
if (data.error) {
g_form.showFieldMsg('server', 'Error: ' + data.error, 'error');
return;
}
// Clear existing options
g_form.clearOptions('server');
// Add new options from API response
g_form.addOption('server', '', '-- Select a server --');
for (var i = 0; i < data.servers.length; i++) {
g_form.addOption('server', data.servers[i].id, data.servers[i].name);
}
g_form.hideFieldMsg('server', true);
} catch (ex) {
g_form.showFieldMsg('server', 'Error processing response', 'error');
}
});
}
Security Considerations
✅ DO:
- Use GlideAjax for all client-to-server communication
- Store credentials in REST Message configurations, never in code
- Implement proper error handling and logging
- Check
gs.isLoggedIn()in Script Includes - Validate and sanitize all input parameters
- Use HTTPS for all external API calls
❌ DON'T:
- Make direct XMLHttpRequest calls from client scripts to external APIs
- Expose API keys or credentials in client-side code
- Use synchronous GlideAjax calls (
getXMLWait()) - Skip error handling or validation
- Store sensitive data in client-side variables
Common Pitfalls and Solutions
Pitfall 1: "My Script Include isn't being called"
Solution: Ensure the Script Include is marked as Client callable and the function extends global.AbstractAjaxProcessor.
Pitfall 2: "The API call is slow and blocking the UI"
Solution: Always use asynchronous GlideAjax calls with callback functions, never getXMLWait().
Pitfall 3: "I'm getting CORS errors"
Solution: You shouldn't see CORS errors because the API call happens server-side via RESTMessageV2, not from the browser.
Pitfall 4: "My credentials are exposed"
Solution: Store all credentials in the REST Message configuration, not in code. Use ServiceNow's credential store.
Performance Optimization Tips
- Cache responses when appropriate (use server-side caching in Script Include)
- Implement timeouts in your REST Message configuration
- Paginate large datasets rather than fetching everything at once
- Debounce onChange events if users type quickly
- Show loading indicators to improve perceived performance
Key Takeaway for Your CSA Exam:
Real-time form population? Think Client Script + GlideAjax + Script Include + RESTMessageV2.
Post-submission automation? Think Flow Designer + IntegrationHub.
Understanding this critical distinction is fundamental to passing your CSA and building robust, maintainable ServiceNow solutions. Don't fall into the trap of direct client-side API calls or forcing server-side automation where it doesn't belong!
CSA Exam Study Points
For the exam, remember:
- GlideAjax is the secure bridge between client and server
- Script Includes must be marked Client callable to be called from GlideAjax
- RESTMessageV2 is used for outbound REST API calls from the server
- Flow Designer cannot directly populate client-side form fields in real-time
- Business Rules run server-side and cannot directly manipulate the client-side form
Practice Scenarios
Test your understanding with these scenarios:
Scenario 1: You need to populate a "Department Manager" field based on the selected department. Which approach is correct?
- ✅ onChange Client Script → GlideAjax → Script Include queries user table
- ❌ Business Rule to set the value after submission
- ❌ Direct XMLHttpRequest to ServiceNow REST API
Scenario 2: After a catalog item is submitted, you need to create a record in an external system. Which approach is correct?
- ❌ Client Script with GlideAjax
- ✅ Flow Designer with REST API integration
- ❌ UI Action with RESTMessageV2
Understanding when to use each integration pattern will make you a more effective ServiceNow administrator and help you ace the CSA exam!
Ready to Master the CSA Exam?
Join our comprehensive study platform and get access to practice tests, study guides, and expert coaching.