Increase Data Action Execution Timeout in Genesys Cloud CX

Increase Data Action Execution Timeout in Genesys Cloud CX

What You Will Build

  • A script that updates the executionTimeout property of a specific Genesys Cloud Data Action to allow longer-running processes.
  • This tutorial uses the Genesys Cloud CX REST API (/api/v2/flows/dataactions) and the Python SDK.
  • The programming language covered is Python 3.8+.

Prerequisites

  • OAuth Client Type: Service Account (Client Credentials) is recommended for API automation.
  • Required Scopes: dataaction:write is required to update data actions. flow:read is required to fetch the current configuration.
  • SDK Version: genesys-cloud-python v100.0.0 or later.
  • Language/Runtime: Python 3.8 or higher.
  • External Dependencies:
    pip install genesys-cloud-python requests
    

Authentication Setup

Genesys Cloud uses OAuth 2.0 for authentication. For programmatic access, the Client Credentials flow is the standard approach. You must configure a Service Account in the Genesys Cloud Admin Console with the necessary permissions.

Step 1: Configure the Service Account

  1. Navigate to Admin > Security > Service Accounts.
  2. Create a new Service Account or select an existing one.
  3. Add the following scopes to the account:
    • dataaction:write
    • flow:read
  4. Note the Client ID and Client Secret.

Step 2: Initialize the SDK Client

The following code initializes the PureCloudPlatformClientV2 client. This client handles token acquisition and caching automatically when configured correctly.

import os
from purecloudplatformclientv2 import (
    PlatformClient,
    DataActionsApi,
    DataAction
)

def get_platform_client() -> PlatformClient:
    """
    Initializes and returns a configured Genesys Cloud Platform Client.
    """
    # Load credentials from environment variables
    client_id = os.getenv("GENESYS_CLIENT_ID")
    client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    
    if not client_id or not client_secret:
        raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set in environment.")

    # Create the platform client
    client = PlatformClient()
    
    # Configure OAuth using Client Credentials flow
    # The SDK caches the token and refreshes it automatically before expiration
    client.set_oauth_client_credentials(client_id, client_secret)
    
    return client

# Initialize the API client
platform_client = get_platform_client()
data_actions_api = DataActionsApi(platform_client)

Note on Scopes: The DataActionsApi requires dataaction:write to perform PUT operations. If you only have dataaction:read, the API will return a 403 Forbidden error.

Implementation

Step 1: Retrieve the Existing Data Action

You cannot update a Data Action by specifying only the timeout. The Genesys Cloud API requires a full object representation (or at least the immutable identifiers and the fields you wish to change) to perform an update. You must first fetch the current configuration to preserve other settings such as type, script, and inputVariables.

Endpoint: GET /api/v2/flows/dataactions/{dataActionId}

def fetch_data_action(data_action_id: str) -> DataAction:
    """
    Fetches the current configuration of a Data Action.
    
    Args:
        data_action_id: The unique identifier of the Data Action.
        
    Returns:
        The DataAction object.
        
    Raises:
        Exception: If the API call fails.
    """
    try:
        # The SDK method handles pagination if needed, but Data Action IDs are unique
        result = data_actions_api.get_flows_dataaction(data_action_id)
        
        if result.body is None:
            raise ValueError(f"Data Action with ID {data_action_id} not found.")
            
        return result.body
        
    except Exception as e:
        # Log the specific error for debugging
        print(f"Error fetching Data Action: {e}")
        raise

Expected Response Structure:
The DataAction object contains critical fields:

  • id: The unique identifier.
  • name: The display name.
  • type: Usually http or custom.
  • script: The body of the action (for custom types).
  • executionTimeout: The current timeout in milliseconds.

Step 2: Update the Execution Timeout

The executionTimeout field is defined in milliseconds. The default is often 3000 ms (3 seconds). To increase this to 5 seconds, you must set it to 5000. To support longer processes, you might set it to 30000 (30 seconds) or higher, up to the platform limit (typically 60,000 ms for HTTP actions, depending on your specific license and configuration).

Endpoint: PUT /api/v2/flows/dataactions/{dataActionId}

def update_data_action_timeout(data_action_id: str, new_timeout_ms: int) -> DataAction:
    """
    Updates the execution timeout of a specific Data Action.
    
    Args:
        data_action_id: The unique identifier of the Data Action.
        new_timeout_ms: The new timeout value in milliseconds.
        
    Returns:
        The updated DataAction object.
    """
    # Step 1: Fetch the current configuration
    current_action = fetch_data_action(data_action_id)
    
    # Step 2: Modify the timeout
    # Ensure the timeout is within valid bounds (e.g., max 60000 ms for HTTP)
    if new_timeout_ms > 60000:
        raise ValueError("Execution timeout cannot exceed 60000 ms for this action type.")
        
    current_action.execution_timeout = new_timeout_ms
    
    # Step 3: Perform the update
    try:
        # The SDK sends a PUT request with the full object
        result = data_actions_api.put_flows_dataaction(data_action_id, body=current_action)
        
        if result.body is None:
            raise ValueError("Update returned no body. Check for API errors.")
            
        print(f"Successfully updated timeout for Data Action '{current_action.name}' to {new_timeout_ms} ms.")
        return result.body
        
    except Exception as e:
        print(f"Error updating Data Action: {e}")
        raise

Why Full Object Update?
Genesys Cloud Data Actions are complex objects. Unlike simple key-value stores, they contain nested structures for input/output variables, error handling, and script bodies. The API requires the PUT payload to be a valid DataAction schema. Sending only { "executionTimeout": 5000 } will result in a 400 Bad Request because required fields like type and id will be missing.

Step 3: Verify the Update

After updating, it is best practice to re-fetch the object to confirm the change persisted. This also helps debug issues where the API might have rejected the update silently due to validation errors.

def verify_update(data_action_id: str, expected_timeout_ms: int) -> bool:
    """
    Verifies that the timeout was updated correctly.
    """
    try:
        updated_action = fetch_data_action(data_action_id)
        
        if updated_action.execution_timeout == expected_timeout_ms:
            print(f"Verification passed: Timeout is now {expected_timeout_ms} ms.")
            return True
        else:
            print(f"Verification failed: Expected {expected_timeout_ms} ms, got {updated_action.execution_timeout} ms.")
            return False
            
    except Exception as e:
        print(f"Verification error: {e}")
        return False

Complete Working Example

The following script combines all steps into a single executable module. It includes error handling, environment variable loading, and a main execution block.

import os
import sys
from purecloudplatformclientv2 import (
    PlatformClient,
    DataActionsApi,
    DataAction
)

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")
    
    if not client_id or not client_secret:
        raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set in environment.")

    client = PlatformClient()
    client.set_oauth_client_credentials(client_id, client_secret)
    return client

def update_data_action_timeout(data_action_id: str, new_timeout_ms: int) -> bool:
    """
    Fetches, updates, and verifies the execution timeout of a Data Action.
    
    Args:
        data_action_id: The unique identifier of the Data Action.
        new_timeout_ms: The new timeout value in milliseconds.
        
    Returns:
        True if successful, False otherwise.
    """
    platform_client = get_platform_client()
    data_actions_api = DataActionsApi(platform_client)
    
    try:
        # 1. Fetch current configuration
        print(f"Fetching Data Action ID: {data_action_id}...")
        result = data_actions_api.get_flows_dataaction(data_action_id)
        
        if result.body is None:
            print("Error: Data Action not found.")
            return False
            
        current_action = result.body
        print(f"Current timeout: {current_action.execution_timeout} ms")
        
        # 2. Validate new timeout
        if new_timeout_ms > 60000:
            print("Error: Timeout exceeds maximum allowed value of 60000 ms.")
            return False
            
        # 3. Update the object
        current_action.execution_timeout = new_timeout_ms
        
        print(f"Updating timeout to {new_timeout_ms} ms...")
        update_result = data_actions_api.put_flows_dataaction(data_action_id, body=current_action)
        
        if update_result.body is None:
            print("Error: Update returned no body.")
            return False
            
        # 4. Verify the change
        verify_result = data_actions_api.get_flows_dataaction(data_action_id)
        if verify_result.body.execution_timeout == new_timeout_ms:
            print("Success: Timeout updated and verified.")
            return True
        else:
            print("Warning: Verification mismatch.")
            return False
            
    except Exception as e:
        print(f"Exception occurred: {str(e)}")
        return False

if __name__ == "__main__":
    # Configuration
    DATA_ACTION_ID = os.getenv("DATA_ACTION_ID")
    NEW_TIMEOUT = int(os.getenv("NEW_TIMEOUT_MS", 5000)) # Default to 5 seconds
    
    if not DATA_ACTION_ID:
        print("Error: DATA_ACTION_ID environment variable is required.")
        sys.exit(1)
        
    success = update_data_action_timeout(DATA_ACTION_ID, NEW_TIMEOUT)
    sys.exit(0 if success else 1)

How to Run:

export GENESYS_CLIENT_ID="your_client_id"
export GENESYS_CLIENT_SECRET="your_client_secret"
export DATA_ACTION_ID="your_data_action_id"
export NEW_TIMEOUT_MS=5000

python update_data_action.py

Common Errors & Debugging

Error: 403 Forbidden

Cause: The Service Account does not have the dataaction:write scope.

Fix:

  1. Go to Admin > Security > Service Accounts.
  2. Select your Service Account.
  3. Under Scopes, ensure dataaction:write is checked.
  4. Save changes.
  5. Wait 1-2 minutes for the permission to propagate.

Code Check:
Ensure your client initialization uses the correct Client ID and Client Secret.

Error: 400 Bad Request

Cause: The JSON payload sent to the PUT endpoint is malformed or missing required fields.

Fix:

  1. Ensure you are sending the full DataAction object retrieved from the GET call.
  2. Check that the type field is present (e.g., "http" or "custom").
  3. Verify that executionTimeout is an integer, not a string.

Debugging Code:

import json

# Before sending the PUT request, log the payload
print("Payload to be sent:")
print(json.dumps(current_action.to_dict(), indent=2))

Error: 429 Too Many Requests

Cause: You have exceeded the API rate limit for your organization or client.

Fix:
Implement exponential backoff in your retry logic.

import time

def retry_with_backoff(func, *args, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            if "429" in str(e) or "rate limit" in str(e).lower():
                wait_time = 2 ** attempt
                print(f"Rate limited. Waiting {wait_time} seconds...")
                time.sleep(wait_time)
            else:
                raise
    raise Exception("Max retries exceeded.")

Error: Timeout Still 3 Seconds After Update

Cause: The Data Action is used in a Flow that has its own global timeout settings, or the browser/client cache is showing the old version.

Fix:

  1. Verify the update by calling the GET endpoint again (as shown in Step 3).
  2. Check the Flow configuration. If the Flow itself has a low timeout setting, the Data Action timeout may be overridden.
  3. Clear any local caches if you are viewing the Data Action in the Genesys Cloud Admin UI.

Official References