Fixing INVALID_FUNCTION in CXone Studio Snippets: Correct Syntax for GetRESTProxy()
What You Will Build
- You will create a CXone Studio Snippet that successfully executes an external HTTP GET request using the
GetRESTProxy()method. - You will resolve the common
INVALID_FUNCTIONruntime error caused by incorrect object instantiation or missing context references. - The tutorial covers JavaScript (ECMAScript 5/6 compatible) syntax within the NICE CXone Studio Snippet execution environment.
Prerequisites
- Platform: NICE CXone Studio.
- Component: Snippet (JavaScript).
- Knowledge: Basic understanding of JavaScript object-oriented programming and HTTP methods.
- Dependencies: None external. The
GetRESTProxymethod is built into the CXone Studio runtime context. - Permissions: The user running the flow must have permissions to execute Studio flows. The external endpoint must be accessible from the CXone cloud environment (publicly accessible or via a configured private endpoint).
Authentication Setup
CXone Studio Snippets run within a secure sandbox. You do not configure OAuth tokens in the snippet code itself. The runtime handles authentication to the CXone platform internally.
However, if you are calling an external API that requires authentication, you must handle that in the headers or query parameters of the REST call. For this tutorial, we will target a public API (https://jsonplaceholder.typicode.com) that requires no authentication.
If you are calling a CXone internal API (e.g., /api/v2/users/me), the runtime often injects the necessary bearer token automatically if you use specific internal proxy methods, but GetRESTProxy is typically used for external calls. For external calls, you manage the auth headers manually.
Implementation
Step 1: Understanding the Runtime Context and the INVALID_FUNCTION Error
The INVALID_FUNCTION error in a CXone Studio Snippet usually occurs for one of two reasons:
- Incorrect Invocation: You are trying to call
GetRESTProxy()as a global function, but it is a method of thecontextobject (or the implicitthiscontext in some older snippet versions, though explicitcontextis preferred). - Method Mismatch: You are calling
GetRESTProxybut the runtime expectsGetRestProxy(case sensitivity matters in strict mode) or you are missing the()parentheses.
In the modern CXone Studio JavaScript environment, the entry point for your snippet is a function that receives a context object. This object contains all available runtime methods.
Incorrect Code (Causes INVALID_FUNCTION):
// This will fail because GetRESTProxy is not a global function
var proxy = GetRESTProxy();
Correct Code Pattern:
// The context object is passed into the snippet function
function execute(context) {
// GetRESTProxy is a method on the context object
var proxy = context.GetRESTProxy();
// ... rest of logic
}
Step 2: Initializing the REST Proxy
Once you have the correct reference, you must initialize the proxy. The GetRESTProxy() method returns an object that manages the HTTP connection. You do not “new” this object; you retrieve the singleton instance from the context.
After retrieving the proxy, you must define the request details. The CXone Studio REST Proxy API is synchronous in execution but asynchronous in the sense that it blocks the snippet thread until the response is received.
Code Block: Retrieving the Proxy
function execute(context) {
// 1. Retrieve the REST Proxy instance from the context
var restProxy = context.GetRESTProxy();
// 2. Define the target URL
var targetUrl = "https://jsonplaceholder.typicode.com/posts/1";
// 3. Define the HTTP method
var httpMethod = "GET";
// 4. Define headers (optional but recommended for content-type)
var headers = {
"Accept": "application/json",
"Content-Type": "application/json"
};
// 5. Define the body (null for GET requests)
var requestBody = null;
try {
// Execute the call
var response = restProxy.Call(targetUrl, httpMethod, headers, requestBody);
// Process response
context.output.success = true;
context.output.statusCode = response.statusCode;
context.output.body = JSON.parse(response.body);
} catch (e) {
context.output.success = false;
context.output.error = e.message;
}
}
Step 3: Handling the Response and Parsing JSON
The Call method returns an object containing statusCode, headers, and body. The body is a string. You must parse it if it is JSON.
A common mistake is assuming the body is already a JavaScript object. It is not. If you attempt to access response.body.id directly without parsing, you will get undefined.
Code Block: Robust Response Handling
function execute(context) {
var restProxy = context.GetRESTProxy();
var url = "https://jsonplaceholder.typicode.com/posts/1";
try {
var response = restProxy.Call(url, "GET", {}, null);
// Check for HTTP success (2xx)
if (response.statusCode >= 200 && response.statusCode < 300) {
var jsonData = JSON.parse(response.body);
// Output the parsed data to the flow
context.output.postId = jsonData.id;
context.output.title = jsonData.title;
context.output.success = true;
} else {
// Handle HTTP errors (4xx, 5xx)
context.output.success = false;
context.output.statusCode = response.statusCode;
context.output.errorMessage = "HTTP Error: " + response.statusCode;
}
} catch (error) {
// Handle network errors or JSON parse errors
context.output.success = false;
context.output.errorMessage = "Snippet Error: " + error.message;
}
}
Step 4: Making a POST Request with a Payload
For POST, PUT, or PATCH requests, you must provide a JSON string in the requestBody parameter. Do not pass a JavaScript object directly; the proxy expects a string.
Code Block: POST Request
function execute(context) {
var restProxy = context.GetRESTProxy();
var url = "https://jsonplaceholder.typicode.com/posts";
// Create the payload object
var payload = {
"title": "foo",
"body": "bar",
"userId": 1
};
// Convert to JSON string
var jsonBody = JSON.stringify(payload);
var headers = {
"Content-Type": "application/json"
};
try {
// Note: requestBody is the 4th parameter
var response = restProxy.Call(url, "POST", headers, jsonBody);
if (response.statusCode === 201) {
var newPost = JSON.parse(response.body);
context.output.success = true;
context.output.newId = newPost.id;
} else {
context.output.success = false;
context.output.error = "Failed to create post. Status: " + response.statusCode;
}
} catch (e) {
context.output.success = false;
context.output.error = e.message;
}
}
Complete Working Example
This is a complete, copy-pasteable CXone Studio Snippet script. It performs a GET request to a public API, parses the JSON, and outputs specific fields to the flow variables.
Snippet Name: FetchPostData
Input Variables: None
Output Variables: success (Boolean), postId (Number), title (String), body (String), error (String)
/**
* CXone Studio Snippet: Fetch Post Data
*
* This snippet demonstrates the correct usage of context.GetRESTProxy()
* to avoid INVALID_FUNCTION errors.
*
* Output Variables:
* - success: Boolean indicating if the call succeeded.
* - postId: The ID of the fetched post.
* - title: The title of the post.
* - body: The body content of the post.
* - error: Error message if the call failed.
*/
function execute(context) {
// Initialize output variables to defaults
context.output.success = false;
context.output.error = null;
context.output.postId = null;
context.output.title = null;
context.output.body = null;
// 1. Correctly retrieve the REST Proxy from the context object
// Calling GetRESTProxy() without 'context.' will cause INVALID_FUNCTION
var restProxy = context.GetRESTProxy();
// 2. Define request parameters
var targetUrl = "https://jsonplaceholder.typicode.com/posts/1";
var httpMethod = "GET";
// Headers: Always set Accept to application/json for JSON APIs
var headers = {
"Accept": "application/json",
"User-Agent": "CXone-Studio-Snippet/1.0"
};
// Body: Null for GET requests
var requestBody = null;
try {
// 3. Execute the HTTP Call
// Signature: Call(url, method, headers, body)
var httpResponse = restProxy.Call(targetUrl, httpMethod, headers, requestBody);
// 4. Validate HTTP Status Code
if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) {
// 5. Parse JSON Body
// The body is a string, not an object
var jsonData = JSON.parse(httpResponse.body);
// 6. Map response data to output variables
context.output.success = true;
context.output.postId = jsonData.id;
context.output.title = jsonData.title;
context.output.body = jsonData.body;
} else {
// Handle non-2xx status codes
context.output.error = "HTTP Error: " + httpResponse.statusCode + " " + httpResponse.body;
}
} catch (exception) {
// Handle runtime exceptions (Network errors, JSON parse errors, etc.)
context.output.error = "Snippet Exception: " + exception.message;
}
}
Common Errors & Debugging
Error: INVALID_FUNCTION
What causes it:
This error occurs when the JavaScript engine cannot find the function definition. In CXone Studio, this is almost always because GetRESTProxy is called as a global function instead of a method on the context object.
How to fix it:
Ensure you are using context.GetRESTProxy().
Code showing the fix:
// WRONG
var proxy = GetRESTProxy();
// RIGHT
var proxy = context.GetRESTProxy();
Error: TypeError: Cannot read property ‘id’ of undefined
What causes it:
You attempted to access a property on response.body directly (e.g., response.body.id) without parsing the JSON string first.
How to fix it:
Always use JSON.parse() on the response body before accessing nested properties.
Code showing the fix:
// WRONG
var title = response.body.title;
// RIGHT
var data = JSON.parse(response.body);
var title = data.title;
Error: SyntaxError: Unexpected token in JSON at position 0
What causes it:
The JSON.parse() function failed because the response body was empty, contained HTML (e.g., an error page), or was not valid JSON.
How to fix it:
Check the response.statusCode before parsing. Also, log the raw response.body in a debug variable to inspect the content.
Code showing the fix:
if (response.statusCode === 200 && response.body) {
try {
var data = JSON.parse(response.body);
// process data
} catch (parseError) {
context.output.error = "Invalid JSON format returned by API";
}
} else {
context.output.error = "Non-200 response or empty body";
}
Error: Maximum execution time exceeded
What causes it:
The external API took too long to respond. CXone Studio Snippets have a timeout limit (typically a few seconds). If the restProxy.Call does not return within this window, the snippet fails.
How to fix it:
Optimize the external API call. Ensure the endpoint is low-latency. Avoid calling slow endpoints from within a snippet. Consider using an Integration (REST Connector) instead if the timeout cannot be resolved, as Integrations may have different timeout configurations or retry logic.