Increase Genesys Cloud Data Action Timeouts Beyond the 3-Second Default

Increase Genesys Cloud Data Action Timeouts Beyond the 3-Second Default

What You Will Build

  • You will configure a Genesys Cloud Flow Data Action to execute long-running HTTP requests (e.g., 5 seconds or more) without triggering a timeout error.
  • You will use the Genesys Cloud Platform API to update the timeout parameter on the Data Action object.
  • You will use Python with the official genesyscloud SDK to automate this configuration change.

Prerequisites

  • OAuth Client: A Genesys Cloud OAuth client with the following scopes:
    • flow:write (to update the flow)
    • flow:read (to read the current flow structure)
  • SDK: Genesys Cloud Python SDK (genesyscloud package, version 135.0.0 or later).
  • Runtime: Python 3.8+.
  • Dependencies: pip install genesyscloud

Authentication Setup

The Genesys Cloud SDK handles OAuth token acquisition and refresh automatically. You must initialize the platform client with your client ID, client secret, and environment.

import os
from purecloudplatformclientv2 import PlatformClient
from purecloudplatformclientv2.rest import ApiException

def get_platform_client() -> PlatformClient:
    """
    Initializes and returns a configured Genesys Cloud Platform Client.
    """
    client_id = os.getenv("GENESYS_CLIENT_ID")
    client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    environment = os.getenv("GENESYS_ENVIRONMENT", "mypurecloud.com")

    if not client_id or not client_secret:
        raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET environment variables are required.")

    platform_client = PlatformClient()
    platform_client.set_environment(environment)
    
    try:
        platform_client.authenticate_client_credentials(client_id, client_secret)
        return platform_client
    except ApiException as e:
        print(f"Authentication failed: {e.status} {e.reason}")
        raise

platform_client = get_platform_client()

Implementation

Step 1: Retrieve the Current Flow Structure

You cannot update the Data Action timeout directly via a patch request to the Data Action endpoint alone. You must retrieve the entire Flow object, modify the specific Data Action node within the flow definition, and then update the entire Flow object.

First, identify the Flow ID and the Data Action node ID. The Flow ID is visible in the URL of the Flow Builder. The Data Action node ID is an internal identifier found in the Flow JSON structure.

from purecloudplatformclientv2 import FlowApi, GetFlowResponse, GetFlowNodeResponse

def get_flow(platform_client: PlatformClient, flow_id: str) -> GetFlowResponse:
    """
    Retrieves the complete flow structure including nodes.
    """
    flow_api = FlowApi(platform_client)
    
    try:
        # Fetch the flow with all nodes expanded
        flow = flow_api.get_flow(
            flow_id=flow_id,
            expand=["nodes"]
        )
        return flow
    except ApiException as e:
        if e.status == 404:
            print(f"Flow with ID {flow_id} not found.")
        elif e.status == 403:
            print("Insufficient permissions. Ensure 'flow:read' scope is granted.")
        else:
            print(f"API Error: {e.status} {e.reason}")
        raise

# Example usage
FLOW_ID = "your-flow-id-here"
flow_data = get_flow(platform_client, FLOW_ID)

# Inspect the nodes to find the Data Action
if flow_data.nodes:
    for node in flow_data.nodes:
        if node.node_type == "dataaction":
            print(f"Found Data Action Node ID: {node.id}")
            print(f"Current Timeout: {node.settings.get('timeout', 'Not set (default 3s)')}")

Step 2: Locate and Modify the Data Action Node

The timeout parameter for a Data Action is located within the settings dictionary of the node object. The default value is 3 seconds. To support calls taking 5 seconds or longer, you must set this value to a number greater than the expected maximum duration (e.g., 10 seconds).

The maximum allowed timeout for a Data Action is typically 30 seconds. Setting it higher may result in validation errors.

def update_data_action_timeout(flow: GetFlowResponse, node_id: str, new_timeout: int) -> GetFlowResponse:
    """
    Updates the timeout setting for a specific Data Action node within the flow.
    
    Args:
        flow: The GetFlowResponse object containing the flow structure.
        node_id: The ID of the Data Action node to update.
        new_timeout: The new timeout value in seconds (max 30).
        
    Returns:
        The modified GetFlowResponse object.
    """
    if not flow.nodes:
        raise ValueError("Flow has no nodes.")
    
    target_node = None
    for node in flow.nodes:
        if node.id == node_id:
            target_node = node
            break
            
    if not target_node:
        raise ValueError(f"Node with ID {node_id} not found in flow.")
        
    if target_node.node_type != "dataaction":
        raise ValueError(f"Node {node_id} is not a Data Action node. Type: {target_node.node_type}")
        
    # Initialize settings if not present
    if target_node.settings is None:
        target_node.settings = {}
        
    # Update the timeout
    # Note: The value is in seconds. 10 seconds allows for 5s calls with buffer.
    target_node.settings["timeout"] = new_timeout
    
    print(f"Updated node {node_id} timeout to {new_timeout}s")
    return flow

# Example usage
# Assuming you found the node ID in Step 1
NODE_ID = "your-data-action-node-id-here"
NEW_TIMEOUT = 10  # 10 seconds

modified_flow = update_data_action_timeout(flow_data, NODE_ID, NEW_TIMEOUT)

Step 3: Publish the Updated Flow

After modifying the flow object in memory, you must push the changes back to Genesys Cloud. This requires a PUT request to the Flow API. The SDK handles the serialization of the modified object.

def update_flow(platform_client: PlatformClient, flow_id: str, flow_obj: GetFlowResponse) -> dict:
    """
    Updates the flow in Genesys Cloud with the modified structure.
    """
    flow_api = FlowApi(platform_client)
    
    try:
        # Update the flow
        # The SDK automatically converts the GetFlowResponse to the required PutFlowRequest
        updated_flow = flow_api.put_flow(
            flow_id=flow_id,
            body=flow_obj
        )
        
        print(f"Flow {flow_id} updated successfully.")
        print(f"New Version: {updated_flow.version}")
        return updated_flow.to_dict()
        
    except ApiException as e:
        if e.status == 400:
            print("Bad Request. Check the flow structure for validation errors.")
            # Print the error body for detailed validation messages
            print(f"Error Body: {e.body}")
        elif e.status == 409:
            print("Conflict. The flow may be locked or in use.")
        else:
            print(f"API Error: {e.status} {e.reason}")
        raise

# Example usage
result = update_flow(platform_client, FLOW_ID, modified_flow)

Complete Working Example

This script combines all steps into a single executable module. It retrieves the flow, finds the first Data Action node, updates its timeout to 10 seconds, and publishes the change.

import os
import sys
from purecloudplatformclientv2 import PlatformClient, FlowApi
from purecloudplatformclientv2.rest import ApiException

def main():
    """
    Main function to update Data Action timeout in a Genesys Cloud Flow.
    """
    # Configuration
    FLOW_ID = os.getenv("FLOW_ID")
    NODE_ID = os.getenv("NODE_ID")
    NEW_TIMEOUT = int(os.getenv("NEW_TIMEOUT", "10"))
    
    if not FLOW_ID or not NODE_ID:
        print("Error: FLOW_ID and NODE_ID environment variables are required.")
        sys.exit(1)

    # Initialize Platform Client
    client_id = os.getenv("GENESYS_CLIENT_ID")
    client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    environment = os.getenv("GENESYS_ENVIRONMENT", "mypurecloud.com")

    platform_client = PlatformClient()
    platform_client.set_environment(environment)
    
    try:
        platform_client.authenticate_client_credentials(client_id, client_secret)
    except ApiException as e:
        print(f"Authentication failed: {e.status} {e.reason}")
        sys.exit(1)

    flow_api = FlowApi(platform_client)

    try:
        # Step 1: Get the Flow
        print(f"Retrieving flow {FLOW_ID}...")
        flow = flow_api.get_flow(flow_id=FLOW_ID, expand=["nodes"])
        
        if not flow.nodes:
            print("Error: Flow has no nodes.")
            sys.exit(1)

        # Step 2: Find and Update the Node
        node_found = False
        for node in flow.nodes:
            if node.id == NODE_ID:
                if node.node_type != "dataaction":
                    print(f"Error: Node {NODE_ID} is not a Data Action.")
                    sys.exit(1)
                
                # Update timeout
                if node.settings is None:
                    node.settings = {}
                
                old_timeout = node.settings.get("timeout", 3)
                print(f"Updating node {NODE_ID} timeout from {old_timeout}s to {NEW_TIMEOUT}s")
                node.settings["timeout"] = NEW_TIMEOUT
                node_found = True
                break
        
        if not node_found:
            print(f"Error: Node {NODE_ID} not found in flow.")
            sys.exit(1)

        # Step 3: Update the Flow
        print("Publishing changes to Genesys Cloud...")
        updated_flow = flow_api.put_flow(flow_id=FLOW_ID, body=flow)
        
        print(f"Success! Flow version updated to {updated_flow.version}")

    except ApiException as e:
        print(f"API Error: {e.status} {e.reason}")
        if e.body:
            print(f"Response Body: {e.body}")
        sys.exit(1)

if __name__ == "__main__":
    main()

Common Errors & Debugging

Error: 400 Bad Request - Validation Failed

Cause: The timeout value exceeds the maximum allowed limit (30 seconds) or is not a valid integer. Alternatively, the flow structure may have other validation errors unrelated to the timeout.

Fix: Ensure the timeout value is between 1 and 30. If the error persists, check the e.body response for specific field errors.

# Example of checking error details
except ApiException as e:
    if e.status == 400:
        import json
        error_details = json.loads(e.body)
        print("Validation Errors:")
        for error in error_details.get("errors", []):
            print(f"- {error}")

Error: 403 Forbidden - Insufficient Scopes

Cause: The OAuth client used does not have the flow:write scope.

Fix: Go to the Genesys Cloud Admin Console, navigate to Setup > OAuth > Clients, edit your client, and add flow:write to the scopes. Re-authenticate.

Error: 409 Conflict - Flow Locked

Cause: Another user is currently editing the flow in the Flow Builder, or the flow is in a state that prevents updates (e.g., published and active with strict locking).

Fix: Ensure no other users are editing the flow. If the flow is published, you may need to unpublish it, make changes, and republish, depending on your organization’s governance settings.

Error: Node Not Found

Cause: The NODE_ID provided does not match any node in the flow. Node IDs are internal and change if the flow is recreated or significantly restructured.

Fix: Re-run the get_flow script and print all node IDs and their types to identify the correct NODE_ID for the Data Action.

# Debug script to list all nodes
for node in flow.nodes:
    print(f"ID: {node.id}, Type: {node.node_type}, Name: {node.name}")

Official References