Increase Genesys Cloud Data Action Timeouts via API

Increase Genesys Cloud Data Action Timeouts via API

What You Will Build

  • This tutorial demonstrates how to programmatically increase the execution timeout for Genesys Cloud Data Actions, resolving cases where actions fail due to the default 3-second limit.
  • The code uses the Genesys Cloud Platform Client V2 SDK to update Integration Data Action configurations.
  • The examples are provided in Python and JavaScript, covering authentication, retrieval of existing configurations, and application of new timeout values.

Prerequisites

  • OAuth Client Type: Service Account or Password Grant client.
  • Required Scopes:
    • integration:integration:read
    • integration:integration:write
    • integration:dataaction:read (if accessing specific data action metadata)
  • SDK Version:
    • Python: genesys-cloud-py >= 1.0.0
    • JavaScript: genesys-cloud-javascript-client >= 1.0.0
  • Language/Runtime:
    • Python 3.8+
    • Node.js 16+
  • External Dependencies:
    • Python: pip install genesys-cloud-py
    • JavaScript: npm install @genesys/cloud

Authentication Setup

Genesys Cloud APIs require OAuth 2.0 authentication. For server-to-server integrations, such as updating configuration settings, the Service Account flow or Password Grant flow is appropriate. The following examples establish a configured API client instance.

Python Authentication

import os
from purecloudplatformclientv2 import PlatformApiClient, Configuration
from purecloudplatformclientv2.rest import ApiException

def get_platform_client() -> PlatformApiClient:
    """
    Initialize and return a configured Genesys Cloud Platform API Client.
    """
    # Retrieve credentials from environment variables
    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 must be set.")

    # Configure the client
    config = Configuration(
        client_id=client_id,
        client_secret=client_secret,
        host=f"https://{environment}",
    )

    # Create the API client instance
    client = PlatformApiClient(config)
    
    # Authenticate the client
    try:
        client.authenticate()
    except ApiException as e:
        print(f"Authentication failed: {e}")
        raise

    return client

JavaScript Authentication

import { PlatformClient } from '@genesys/cloud';

async function getPlatformClient() {
    const clientId = process.env.GENESYS_CLIENT_ID;
    const clientSecret = process.env.GENESYS_CLIENT_SECRET;
    const environment = process.env.GENESYS_ENVIRONMENT || 'mypurecloud.com';

    if (!clientId || !clientSecret) {
        throw new Error('GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET environment variables must be set.');
    }

    const config = {
        clientId,
        clientSecret,
        host: `https://${environment}`,
    };

    const client = new PlatformClient(config);

    try {
        await client.authenticate();
    } catch (error) {
        console.error('Authentication failed:', error);
        throw error;
    }

    return client;
}

Implementation

Step 1: Retrieve the Integration and Data Action Configuration

Before modifying the timeout, you must identify the specific Integration ID and the Data Action ID associated with the failing call. Data Action timeouts are often defined at the Integration level or within the specific Data Action definition depending on the integration type.

For most custom integrations or standard third-party integrations, the timeout setting resides in the Integration object’s dataActions array or a linked configuration object.

Python: Fetching Integration Details

from purecloudplatformclientv2 import IntegrationsApi

def get_integration_by_name(client: PlatformApiClient, integration_name: str) -> dict:
    """
    Retrieve an integration object by its name.
    """
    integrations_api = IntegrationsApi(client)
    
    try:
        # Fetch all integrations (pagination handled internally for small sets, 
        # but for production, implement pagination loop)
        response = integrations_api.get_integrations(page_size=100)
        
        for integration in response.entities:
            if integration.name == integration_name:
                return integration
        
        raise ValueError(f"Integration '{integration_name}' not found.")
        
    except ApiException as e:
        print(f"Error fetching integrations: {e}")
        raise

JavaScript: Fetching Integration Details

import { IntegrationsApi } from '@genesys/cloud';

async function getIntegrationByName(client, integrationName) {
    const integrationsApi = new IntegrationsApi(client);

    try {
        const response = await integrationsApi.getIntegrations({ pageSize: 100 });

        const integration = response.entities.find(i => i.name === integrationName);

        if (!integration) {
            throw new Error(`Integration '${integrationName}' not found.`);
        }

        return integration;
    } catch (error) {
        console.error('Error fetching integrations:', error);
        throw error;
    }
}

Step 2: Identify the Timeout Parameter

The default timeout for Data Actions is often 3,000 milliseconds (3 seconds). This value is typically located in the timeout field within the dataActions list of the Integration object, or in a specific configuration JSON blob depending on the integration provider.

For Genesys Cloud native Data Actions (like Salesforce, Zendesk, etc.), the timeout might be controlled by the dataActionTimeout property in the Integration object or within the specific DataAction definition if exposed via the API.

Critical Note: Not all integrations expose the timeout field in the API payload. If the timeout field is absent, it may be hardcoded or managed via a different endpoint (e.g., Flow settings if the Data Action is called from a Flow). However, for standard Integrations, the field is usually present.

If the timeout is set at the Flow level (when calling a Data Action from a Flow), you must update the Flow object. If it is set at the Integration level, you update the Integration object. This tutorial focuses on the Integration level, which is the common source of the “3-second default” issue for external API calls.

Inspecting the Payload

When you retrieve the integration, inspect the dataActions array. You will see entries similar to this:

{
  "id": "data-action-id-123",
  "name": "GetCustomerData",
  "timeout": 3000,
  "url": "https://api.example.com/customer",
  "method": "GET"
}

If timeout is missing or set to 3000, this is the value you need to change.

Step 3: Update the Timeout Value

To increase the limit, you must perform a PUT request to the Integration endpoint with the updated payload. The maximum timeout allowed by Genesys Cloud for Data Actions is typically 30,000 milliseconds (30 seconds). Setting it to 5,000 milliseconds (5 seconds) or higher will resolve the 5-second call failure.

Python: Updating the Integration

from purecloudplatformclientv2 import IntegrationsApi, Integration

def update_data_action_timeout(client: PlatformApiClient, integration: Integration, new_timeout_ms: int) -> Integration:
    """
    Update the timeout for all data actions in an integration, or a specific one.
    """
    integrations_api = IntegrationsApi(client)

    # Clone the integration to avoid mutating the original object reference
    updated_integration = Integration(
        id=integration.id,
        name=integration.name,
        enabled=integration.enabled,
        version=integration.version,  # Critical for optimistic locking
        data_actions=integration.data_actions
    )

    if updated_integration.data_actions:
        for action in updated_integration.data_actions:
            # Check if the action has a timeout field that can be modified
            # Note: The SDK model may not have a direct 'timeout' attribute on DataAction 
            # if it is nested in a custom JSON config. 
            # For standard Genesys Data Actions, it is often a direct property.
            
            # Assuming the DataAction object has a 'timeout' attribute
            if hasattr(action, 'timeout'):
                action.timeout = new_timeout_ms
            # If timeout is inside a 'configuration' dict (common for custom integrations)
            elif action.configuration and 'timeout' in action.configuration:
                action.configuration['timeout'] = new_timeout_ms

    try:
        # Update the integration
        response = integrations_api.put_integration(
            integration_id=integration.id,
            body=updated_integration
        )
        print(f"Integration '{integration.name}' updated successfully.")
        return response
    except ApiException as e:
        if e.status == 409:
            print("Conflict: The integration version has changed. Please fetch the latest version and retry.")
        else:
            print(f"Error updating integration: {e}")
        raise

JavaScript: Updating the Integration

import { IntegrationsApi } from '@genesys/cloud';

async function updateDataActionTimeout(client, integration, newTimeoutMs) {
    const integrationsApi = new IntegrationsApi(client);

    // Create a deep copy to avoid mutation issues
    const updatedIntegration = JSON.parse(JSON.stringify(integration));

    if (updatedIntegration.dataActions) {
        updatedIntegration.dataActions.forEach(action => {
            // Standard Genesys Data Action structure
            if (action.timeout !== undefined) {
                action.timeout = newTimeoutMs;
            }
            // Custom integration configuration structure
            else if (action.configuration && action.configuration.timeout !== undefined) {
                action.configuration.timeout = newTimeoutMs;
            }
        });
    }

    try {
        const response = await integrationsApi.putIntegration({
            integrationId: updatedIntegration.id,
            body: updatedIntegration
        });
        console.log(`Integration '${updatedIntegration.name}' updated successfully.`);
        return response;
    } catch (error) {
        if (error.status === 409) {
            console.error('Conflict: The integration version has changed. Please fetch the latest version and retry.');
        } else {
            console.error('Error updating integration:', error);
        }
        throw error;
    }
}

Complete Working Example

The following Python script combines authentication, retrieval, and update logic into a single executable module. It searches for an integration by name and updates the timeout for all its data actions to 10,000 milliseconds (10 seconds).

import os
import sys
from purecloudplatformclientv2 import PlatformApiClient, Configuration, IntegrationsApi, Integration
from purecloudplatformclientv2.rest import ApiException

def main():
    # 1. Setup Authentication
    try:
        client = get_platform_client()
    except Exception as e:
        print(f"Failed to authenticate: {e}")
        sys.exit(1)

    # 2. Configuration
    INTEGRATION_NAME = os.getenv("TARGET_INTEGRATION_NAME", "MyCustomAPI")
    NEW_TIMEOUT_MS = int(os.getenv("NEW_TIMEOUT_MS", "10000"))  # 10 seconds
    MAX_TIMEOUT_MS = 30000  # Genesys Cloud hard limit

    if NEW_TIMEOUT_MS > MAX_TIMEOUT_MS:
        print(f"Warning: Timeout {NEW_TIMEOUT_MS}ms exceeds maximum limit of {MAX_TIMEOUT_MS}ms. Capping at {MAX_TIMEOUT_MS}ms.")
        NEW_TIMEOUT_MS = MAX_TIMEOUT_MS

    # 3. Retrieve Integration
    integrations_api = IntegrationsApi(client)
    target_integration = None

    try:
        response = integrations_api.get_integrations(page_size=100)
        for integration in response.entities:
            if integration.name == INTEGRATION_NAME:
                target_integration = integration
                break
        
        if not target_integration:
            print(f"Integration '{INTEGRATION_NAME}' not found.")
            sys.exit(1)
            
        print(f"Found Integration: {target_integration.id} ({target_integration.name})")
        
    except ApiException as e:
        print(f"Error fetching integrations: {e}")
        sys.exit(1)

    # 4. Update Timeout
    try:
        # Clone the integration object
        updated_integration = Integration(
            id=target_integration.id,
            name=target_integration.name,
            enabled=target_integration.enabled,
            version=target_integration.version,
            data_actions=target_integration.data_actions
        )

        actions_updated = 0
        if updated_integration.data_actions:
            for action in updated_integration.data_actions:
                # Attempt to update standard timeout field
                if hasattr(action, 'timeout') and action.timeout is not None:
                    old_timeout = action.timeout
                    action.timeout = NEW_TIMEOUT_MS
                    print(f"Updated Data Action '{action.name}' timeout from {old_timeout}ms to {NEW_TIMEOUT_MS}ms")
                    actions_updated += 1
                
                # Attempt to update custom configuration timeout
                elif action.configuration and isinstance(action.configuration, dict):
                    if 'timeout' in action.configuration:
                        old_timeout = action.configuration['timeout']
                        action.configuration['timeout'] = NEW_TIMEOUT_MS
                        print(f"Updated Data Action '{action.name}' config timeout from {old_timeout}ms to {NEW_TIMEOUT_MS}ms")
                        actions_updated += 1

        if actions_updated == 0:
            print("No data actions with modifiable timeout fields found.")
            return

        # 5. Commit Changes
        integrations_api.put_integration(
            integration_id=target_integration.id,
            body=updated_integration
        )
        print(f"Successfully updated {actions_updated} data action(s) in Integration '{INTEGRATION_NAME}'.")

    except ApiException as e:
        if e.status == 409:
            print("Conflict Error: The integration was modified by another user since you fetched it. Please run the script again.")
        else:
            print(f"Error updating integration: {e}")
        sys.exit(1)

def get_platform_client() -> PlatformApiClient:
    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 must be set.")

    config = Configuration(
        client_id=client_id,
        client_secret=client_secret,
        host=f"https://{environment}",
    )

    client = PlatformApiClient(config)
    client.authenticate()
    return client

if __name__ == "__main__":
    main()

Common Errors & Debugging

Error: 409 Conflict

  • What causes it: Genesys Cloud uses optimistic locking via the version field. If another user or process modifies the integration between your GET and PUT requests, the server rejects the update.
  • How to fix it: Implement a retry loop that re-fetches the integration, re-applies the timeout changes, and attempts the update again.
  • Code Fix:
def update_with_retry(client, integration_id, update_func, max_retries=3):
    for attempt in range(max_retries):
        try:
            # Fetch latest version
            latest = integrations_api.get_integration(integration_id=integration_id)
            # Apply changes to latest object
            updated = update_func(latest)
            # Attempt update
            integrations_api.put_integration(integration_id=integration_id, body=updated)
            return
        except ApiException as e:
            if e.status == 409 and attempt < max_retries - 1:
                print(f"Version conflict. Retrying ({attempt + 1}/{max_retries})...")
                continue
            raise

Error: 400 Bad Request

  • What causes it: The timeout value exceeds the platform limit (30,000 ms) or is set to an invalid type (e.g., string instead of integer).
  • How to fix it: Validate the NEW_TIMEOUT_MS variable before sending the request. Ensure it is an integer and less than or equal to 30,000.

Error: 401 Unauthorized

  • What causes it: The OAuth token is expired or the client lacks the integration:integration:write scope.
  • How to fix it: Verify the OAuth scopes assigned to the Service Account in the Genesys Cloud Admin Console. Ensure the token is refreshed if using a long-running process.

Error: Timeout Field Not Found

  • What causes it: The specific Data Action type does not support configurable timeouts via the API, or the timeout is managed at the Flow level.
  • How to fix it:
    1. Check if the Data Action is called from a Flow. If so, update the timeout property in the Flow’s contactForm or specific Action node within the Flow JSON.
    2. If using a custom Integration, ensure the configuration JSON blob includes the timeout key. Some third-party integrations require you to define the timeout in the configuration object rather than a top-level field.

Official References