Increase Data Action Execution Timeout in Genesys Cloud CX
What You Will Build
- A script that updates the
executionTimeoutproperty 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:writeis required to update data actions.flow:readis required to fetch the current configuration. - SDK Version:
genesys-cloud-pythonv100.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
- Navigate to Admin > Security > Service Accounts.
- Create a new Service Account or select an existing one.
- Add the following scopes to the account:
dataaction:writeflow:read
- 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: Usuallyhttporcustom.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:
- Go to Admin > Security > Service Accounts.
- Select your Service Account.
- Under Scopes, ensure
dataaction:writeis checked. - Save changes.
- 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:
- Ensure you are sending the full
DataActionobject retrieved from theGETcall. - Check that the
typefield is present (e.g.,"http"or"custom"). - Verify that
executionTimeoutis 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:
- Verify the update by calling the
GETendpoint again (as shown in Step 3). - Check the Flow configuration. If the Flow itself has a low timeout setting, the Data Action timeout may be overridden.
- Clear any local caches if you are viewing the Data Action in the Genesys Cloud Admin UI.