Fixing INVALID_FUNCTION Errors in CXone Studio: Correct Syntax for GetRESTProxy()
What You Will Build
- A functional CXone Studio Snippet that executes an outbound HTTP GET request using the
GetRESTProxy()object. - The solution resolves the common
INVALID_FUNCTIONruntime error caused by incorrect object instantiation or method chaining. - The tutorial covers C# syntax within the CXone Studio Snippet environment, including proper header configuration and response parsing.
Prerequisites
- CXone Studio Access: You must have access to a CXone tenant with Studio enabled.
- Snippet Environment: Familiarity with the CXone Studio Snippet editor (C#-based scripting environment).
- Target API: A valid public endpoint for testing (e.g.,
https://jsonplaceholder.typicode.com/todos/1). - No External Dependencies: Snippets run in a sandboxed environment; you cannot install NuGet packages. You rely on the pre-loaded
NICE.InContactand standard .NET libraries.
Authentication Setup
CXone Studio Snippets do not require external OAuth flows. The execution context inherits the permissions of the user or application running the flow. However, the outbound HTTP request made by the snippet may require authentication headers (e.g., API Keys, Bearer Tokens).
For this tutorial, we will assume the target endpoint is public. If you are calling a protected API, you must inject the Authorization header manually in the snippet code.
Implementation
Step 1: Understanding the INVALID_FUNCTION Error
The INVALID_FUNCTION error in CXone Studio typically occurs when the runtime engine cannot resolve a method call on an object. In the context of GetRESTProxy(), this usually stems from one of three mistakes:
- Treating
GetRESTProxyas a static method: Attempting to callGetRESTProxy.Get(...)instead of instantiating the object first. - Incorrect Method Chaining: Trying to chain
.Execute()directly on the builder without finalizing the request object. - Missing Namespace References: While
GetRESTProxyis often globally available in newer Studio versions, explicit referencing ofNICE.InContactnamespaces can sometimes resolve ambiguity.
The correct pattern is:
- Instantiate the REST Proxy object.
- Configure the request (URL, Method, Headers).
- Execute the request.
- Parse the response.
Step 2: Instantiating the REST Proxy
Do not attempt to create a new HttpClient or WebRequest object manually. The sandboxed environment restricts direct network sockets. You must use the provided GetRESTProxy() function.
// INCORRECT: This causes INVALID_FUNCTION because GetRESTProxy is not a class with static members
// var response = GetRESTProxy.Get("https://example.com");
// CORRECT: Instantiate the proxy object
var restProxy = GetRESTProxy();
Step 3: Configuring the Request
The restProxy object exposes methods to configure the HTTP request. You must set the URL and the HTTP method explicitly.
// Set the target URL
restProxy.Url = "https://jsonplaceholder.typicode.com/todos/1";
// Set the HTTP Method (GET, POST, PUT, DELETE, PATCH)
restProxy.Method = "GET";
// Set Timeout (in milliseconds). Default is often 30000, but explicit is safer.
restProxy.Timeout = 10000;
Step 4: Adding Headers and Body (If Required)
For GET requests, you rarely need a body, but headers are common for API keys or Content-Type declarations. For POST/PUT, you must set the body.
// Adding Headers
// Use the AddHeader method. Key is header name, Value is header content.
restProxy.AddHeader("Accept", "application/json");
restProxy.AddHeader("Content-Type", "application/json");
// If you were doing a POST, you would set the body like this:
// var payload = "{\"key\":\"value\"}";
// restProxy.Body = payload;
Step 5: Executing and Parsing the Response
This is the most critical step. The Execute() method returns a response object. You must check for success before parsing the body to avoid runtime exceptions on 4xx/5xx errors.
// Execute the request
var response = restProxy.Execute();
// Check the Status Code
if (response.StatusCode >= 200 && response.StatusCode < 300) {
// Success: Parse the body
var responseBody = response.Body;
// Example: Parsing JSON using the built-in JSON helper
// Note: CXone Studio provides a 'Json' namespace for parsing
var jsonResult = Json.Parse(responseBody);
// Access a specific field (e.g., "title" from the todo item)
var title = jsonResult["title"];
// Store in a Flow Variable for later use in the Studio Flow
SetFlowVariable("TodoTitle", title);
} else {
// Failure: Handle error
var errorStatus = response.StatusCode;
var errorMessage = response.Body;
// Log the error to the Studio Trace
Log.Error("REST Call Failed with status: " + errorStatus + " Body: " + errorMessage);
// Optionally set a flow variable to trigger an error path in Studio
SetFlowVariable("ApiError", true);
}
Step 3: Handling Complex JSON Responses
The INVALID_FUNCTION error can also appear if you try to access JSON properties incorrectly. The Json.Parse() method returns a dynamic object. Ensure you use bracket notation [] for string keys.
// Assuming response.Body is: {"user": {"name": "John Doe"}}
var parsed = Json.Parse(response.Body);
// Correct:
var userName = parsed["user"]["name"];
// Incorrect (Causes INVALID_FUNCTION or NullReferenceException):
// var userName = parsed.user.name; // Dot notation may fail if types are not strongly typed
Complete Working Example
Copy and paste this entire block into a new Snippet in CXone Studio. Replace the URL if you need to test against a different endpoint.
using System;
using System.Collections.Generic;
public class Snippet
{
public void Execute()
{
try
{
// 1. Instantiate the REST Proxy
var restProxy = GetRESTProxy();
// 2. Configure the Request
restProxy.Url = "https://jsonplaceholder.typicode.com/todos/1";
restProxy.Method = "GET";
restProxy.Timeout = 5000; // 5 seconds
// 3. Add Headers (Optional but recommended)
restProxy.AddHeader("Accept", "application/json");
restProxy.AddHeader("User-Agent", "CXoneStudioSnippet/1.0");
// 4. Execute the Request
var response = restProxy.Execute();
// 5. Validate Status Code
int statusCode = response.StatusCode;
if (statusCode == 200)
{
// 6. Parse Response Body
string responseBody = response.Body;
Log.Info("Raw Response: " + responseBody);
// Parse JSON
dynamic jsonResult = Json.Parse(responseBody);
// Extract Fields
// The JSON structure for this endpoint is:
// {
// "userId": 1,
// "id": 1,
// "title": "delectus aut autem",
// "completed": false
// }
string title = jsonResult["title"];
int userId = jsonResult["userId"];
bool isCompleted = jsonResult["completed"];
// 7. Set Flow Variables for use in downstream Studio blocks
SetFlowVariable("TodoTitle", title);
SetFlowVariable("TodoUserId", userId.ToString());
SetFlowVariable("TodoCompleted", isCompleted.ToString());
Log.Info("Successfully parsed Todo Title: " + title);
}
else
{
// Handle Non-200 Responses
Log.Error("API Call Failed. Status Code: " + statusCode);
Log.Error("Response Body: " + response.Body);
// Set an error flag for the Studio Flow to handle
SetFlowVariable("ApiCallError", true);
SetFlowVariable("ApiErrorMessage", response.Body);
}
}
catch (Exception ex)
{
// Catch generic exceptions (e.g., network timeout, malformed URL)
Log.Error("Exception in Snippet: " + ex.Message);
Log.Error("Stack Trace: " + ex.StackTrace);
SetFlowVariable("SnippetException", true);
SetFlowVariable("ExceptionMessage", ex.Message);
}
}
}
Common Errors & Debugging
Error: INVALID_FUNCTION on GetRESTProxy
What causes it:
You are likely calling GetRESTProxy as if it were a static method on a class, or you have a syntax error in the instantiation line.
How to fix it:
Ensure you are calling it as a function that returns an object, not a method on an object.
- Wrong:
var proxy = Http.GetRESTProxy(); - Wrong:
var proxy = new GetRESTProxy(); - Correct:
var proxy = GetRESTProxy();
Error: NullReferenceException on response.Body
What causes it:
The request failed (timeout, DNS failure, or 4xx/5xx error) and the Execute() method returned a response object where the Body property is null or empty.
How to fix it:
Always check response.StatusCode before accessing response.Body. Wrap the parsing logic in an if block that verifies the status code is in the 2xx range.
Error: Json.Parse returns unexpected structure
What causes it:
The API returned HTML (e.g., a 404 page) or XML instead of JSON, but you treated it as JSON.
How to fix it:
Log the raw response.Body using Log.Info() before parsing. Inspect the output in the Studio Trace to confirm the content type matches your expectation.
Error: Timeout Exceptions
What causes it:
The target server did not respond within the default timeout window.
How to fix it:
Explicitly set restProxy.Timeout to a higher value (e.g., 15000 for 15 seconds) if the external API is known to be slow. Note that Studio Snippets have a hard maximum execution time (usually 30-60 seconds depending on tenant config), so do not set this excessively high.