Fixing INVALID_FUNCTION in CXone Studio Snippet: Correct Syntax for GetRESTProxy()
What You Will Build
- A CXone Studio Snippet that successfully executes an outbound HTTP request using the
GetRESTProxyfunction without triggering anINVALID_FUNCTIONruntime error. - This tutorial uses the NICE CXone Studio Snippet execution environment and internal platform APIs.
- The language covered is JavaScript (ES5/ES6 compatible within the Studio Snippet sandbox).
Prerequisites
- Environment: NICE CXone Studio.
- Permissions: Access to the Studio environment with rights to create and deploy Snippets.
- Knowledge: Understanding of CXone Studio Snippet lifecycle (Input/Output mappings, Execution context).
- Dependencies: No external npm packages are required. The
GetRESTProxyfunction is a native global object available within the Snippet execution context.
Authentication Setup
CXone Studio Snippets do not require manual OAuth token management for internal platform calls. The Snippet executes under the context of the authenticated user who triggered the flow (or the system context if automated).
When making external HTTP requests via GetRESTProxy, you must handle authentication headers manually in the request payload. For internal CXone API calls, the platform injects the necessary bearer token automatically if you use the correct internal endpoint patterns, or you must pass the token explicitly if calling external services.
This tutorial focuses on the syntax of the proxy object, which is the most common source of the INVALID_FUNCTION error. The error occurs because developers often attempt to instantiate the proxy incorrectly or call methods that do not exist on the returned object.
Implementation
Step 1: Understanding the GetRESTProxy() Signature
The INVALID_FUNCTION error typically arises from one of two mistakes:
- Calling
GetRESTProxyas a constructor (e.g.,new GetRESTProxy()). It is a factory function, not a class. - Attempting to call
.request()directly on the globalGetRESTProxyinstead of on the instance returned by it.
The correct signature is:
var proxy = GetRESTProxy();
This returns an object with a .request(config) method. The config object must adhere to a specific structure expected by the CXone runtime.
Step 2: Constructing the Valid Request Configuration
The config object passed to .request() is strict. Missing fields or incorrect types will cause silent failures or runtime errors.
Critical Fields:
url: String. The full endpoint.method: String. HTTP method (GET, POST, PUT, DELETE). Must be uppercase.headers: Object. Key-value pairs for HTTP headers.body: String or Object. For POST/PUT, this contains the payload. If an object, it must be JSON-serialized by the proxy, but explicit stringification is safer.timeout: Integer. Timeout in milliseconds.
Common Pitfall:
Developers often include contentType or accept as separate top-level properties. These must be inside the headers object.
// INCORRECT - Causes INVALID_FUNCTION or unexpected behavior
var config = {
url: "https://api.example.com/data",
method: "POST",
contentType: "application/json", // WRONG: Not a top-level property
headers: {
"Authorization": "Bearer token"
},
body: { key: "value" }
};
// CORRECT
var config = {
url: "https://api.example.com/data",
method: "POST",
headers: {
"Authorization": "Bearer token",
"Content-Type": "application/json" // CORRECT: Inside headers
},
body: JSON.stringify({ key: "value" }), // Explicit stringification is recommended
timeout: 5000
};
Step 3: Executing the Request and Handling the Response
The .request() method is synchronous within the Snippet context but behaves like a blocking call. It returns a response object.
Response Object Structure:
status: Integer (e.g., 200, 404, 500).body: String (The raw response body). You must parse this JSON manually.headers: Object (Response headers).error: String (If an error occurred during the network call).
try {
// 1. Instantiate the Proxy
var proxy = GetRESTProxy();
// 2. Define Configuration
var config = {
url: "https://jsonplaceholder.typicode.com/posts/1",
method: "GET",
headers: {
"Accept": "application/json"
},
timeout: 10000
};
// 3. Execute Request
var response = proxy.request(config);
// 4. Validate Status
if (response.status >= 200 && response.status < 300) {
// 5. Parse Body
var data = JSON.parse(response.body);
// Log success for debugging
console.log("Success: " + data.title);
// Return data for downstream use
return {
success: true,
data: data
};
} else {
console.error("HTTP Error: " + response.status + " - " + response.body);
return {
success: false,
error: "HTTP " + response.status
};
}
} catch (e) {
// This catches INVALID_FUNCTION or JSON parsing errors
console.error("Snippet Error: " + e.message);
return {
success: false,
error: e.message
};
}
Complete Working Example
Below is a complete, copy-pasteable Snippet script. This example calls the public jsonplaceholder API to retrieve a user profile. It demonstrates proper error handling, header configuration, and JSON parsing.
Instructions:
- In CXone Studio, create a new Snippet.
- Set the Input parameters to empty (or define specific inputs if you want to parameterize the URL).
- Set the Output parameters to
success(Boolean) andresult(String/JSON). - Paste the following code into the Script editor.
/**
* CXone Studio Snippet: Safe GetRESTProxy Usage
*
* Purpose: Demonstrates correct instantiation and usage of GetRESTProxy
* to avoid INVALID_FUNCTION errors.
*
* Input: None
* Output:
* - success (boolean): Whether the request succeeded
* - result (string): JSON string of the response body
* - statusCode (integer): HTTP status code
*/
// Define the target URL.
// In production, replace this with a variable from Input mapping.
var targetUrl = "https://jsonplaceholder.typicode.com/users/1";
try {
// STEP 1: Instantiate the REST Proxy
// Note: GetRESTProxy is a global function. Do NOT use 'new'.
var restProxy = GetRESTProxy();
// STEP 2: Configure the Request
var requestConfig = {
// The full URL including protocol
url: targetUrl,
// HTTP Method (Must be uppercase)
method: "GET",
// Headers object
headers: {
"Accept": "application/json",
"User-Agent": "CXone-Studio-Snippet/1.0"
},
// Timeout in milliseconds (Max usually 10000-30000 depending on org config)
timeout: 5000
};
// STEP 3: Execute the Request
// This is a blocking call. It returns a response object.
var httpResponse = restProxy.request(requestConfig);
// STEP 4: Handle the Response
// Check for network-level errors first
if (httpResponse.error) {
throw new Error("Network Error: " + httpResponse.error);
}
// Check HTTP Status Code
var statusCode = httpResponse.status;
if (statusCode >= 200 && statusCode < 300) {
// Success: Parse the body
var responseBody = httpResponse.body;
// Validate that the body is not empty before parsing
if (!responseBody) {
throw new Error("Empty response body received");
}
var parsedData = JSON.parse(responseBody);
// Return structured output
return {
success: true,
statusCode: statusCode,
result: JSON.stringify(parsedData) // Serialize back to string for output mapping
};
} else {
// HTTP Error (4xx, 5xx)
console.error("HTTP Request Failed with Status: " + statusCode);
console.error("Response Body: " + httpResponse.body);
return {
success: false,
statusCode: statusCode,
result: null
};
}
} catch (exception) {
// STEP 5: Global Error Handling
// This catches INVALID_FUNCTION, JSON.parse errors, or Network timeouts
var errorMessage = exception.message || "Unknown Snippet Error";
console.error("Snippet Exception: " + errorMessage);
return {
success: false,
statusCode: 0,
result: null
};
}
Output Mapping Configuration:
After saving the script, map the output variables:
- success: Map to the
successproperty from the script. - statusCode: Map to the
statusCodeproperty from the script. - result: Map to the
resultproperty from the script.
Common Errors & Debugging
Error: INVALID_FUNCTION
What causes it:
This is the most common error when using GetRESTProxy. It occurs when the runtime cannot find the function or the object structure is malformed.
- Typo in Function Name:
GetRestProxy(lowercase ‘e’) vsGetRESTProxy. - Incorrect Instantiation: Using
new GetRESTProxy(). The function returns an object directly; it is not a constructor. - Scope Issue: Attempting to call
GetRESTProxyinside a nested function that does not have access to the global scope (rare in Studio Snippets, but possible if wrapped in strict IIFEs incorrectly).
How to fix it:
Ensure you are calling GetRESTProxy() exactly as shown:
// Correct
var proxy = GetRESTProxy();
// Incorrect
var proxy = new GetRESTProxy();
var proxy = GetRestProxy();
Error: TypeError: Cannot read property ‘request’ of undefined
What causes it:
This happens if GetRESTProxy() returns undefined. This is extremely rare but can occur if the Studio runtime is in a degraded state or if you are testing in a non-Snippet JavaScript environment (like a browser console).
How to fix it:
Verify that the code is running inside a CXone Studio Snippet node. GetRESTProxy is not available in standard JavaScript environments.
Error: SyntaxError: Unexpected token < in JSON at position 0
What causes it:
You called JSON.parse() on a response body that is HTML (usually an error page from the server) or empty.
How to fix it:
Check the response.body before parsing.
if (response.body && response.body.trim().length > 0) {
var data = JSON.parse(response.body);
} else {
console.warn("Response body is empty or invalid JSON");
}
Error: Timeout
What causes it:
The external server did not respond within the timeout period defined in the config.
How to fix it:
Increase the timeout value in the requestConfig. Note that CXone imposes a maximum timeout limit (often 10 seconds or 30 seconds depending on organization settings). If the endpoint is slow, consider optimizing the external API or using asynchronous patterns if supported by the downstream flow.