How to configure Web Messaging deployment to customize colors and launcher position

How to configure Web Messaging deployment to customize colors and launcher position

What You Will Build

  • A Python script that connects to the Genesys Cloud CX API to retrieve an existing Web Messaging deployment and update its visual configuration.
  • The code modifies the launcher icon color, background color, and the position of the chat launcher button on the web page.
  • This tutorial uses the Genesys Cloud Python SDK (genesyscloud) and the REST API directly for granular control.

Prerequisites

  • OAuth Client: A Genesys Cloud OAuth Client with the scope webchat:deployment:write (and webchat:deployment:read if retrieving the current config).
  • SDK Version: genesyscloud v130.0.0 or later.
  • Language/Runtime: Python 3.8+.
  • External Dependencies:
    pip install genesyscloud requests httpx
    
  • Deployment ID: You must have an existing Web Messaging Deployment ID. If you do not have one, you must create one via the Admin Console or the POST /api/v2/webchat/deployments endpoint first.

Authentication Setup

Genesys Cloud uses OAuth 2.0 for authentication. For server-to-server integrations (like this script), you will use the Client Credentials flow. The SDK handles token acquisition and refresh automatically, but understanding the underlying mechanism is critical for debugging.

SDK Initialization

The genesyscloud SDK provides a PlatformClient that manages the authentication context. You must configure the client with your credentials before making any API calls.

import os
from genesyscloud.platform.client.configuration import Configuration
from genesyscloud.platform.client.api_client import ApiClient
from genesyscloud.webchat.api import WebchatApi

def initialize_genesisys_client() -> WebchatApi:
    """
    Initializes the Genesys Cloud API client using environment variables for credentials.
    
    Returns:
        WebchatApi: An initialized API client instance ready for Webchat operations.
    """
    # Configuration object holds the credentials and base URL
    config = Configuration()
    
    # Set credentials from environment variables
    config.client_id = os.getenv("GENESYS_CLIENT_ID")
    config.client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    config.host = os.getenv("GENESYS_HOST", "https://api.mypurecloud.com")
    
    # Validate that credentials are present
    if not config.client_id or not config.client_secret:
        raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set in environment variables.")

    # Create the API client
    api_client = ApiClient(configuration=config)
    
    # Return the specific API module for Webchat
    return WebchatApi(api_client)

Note: Ensure your OAuth Client has the correct scope. If you attempt to write to a deployment without webchat:deployment:write, the API will return a 403 Forbidden error, regardless of whether authentication succeeded.

Implementation

Step 1: Retrieve the Existing Deployment Configuration

Before modifying a deployment, you must retrieve its current state. Web Messaging deployments contain complex nested objects for UI customization. Attempting to send a PATCH or PUT request with an incomplete payload can inadvertently reset other settings (like language support or routing strategies) to their defaults. Therefore, the standard pattern is: Read → Modify → Write.

API Endpoint

GET /api/v2/webchat/deployments/{deploymentId}

Required Scope: webchat:deployment:read

Code Example

def get_deployment_config(api_client: WebchatApi, deployment_id: str) -> dict:
    """
    Retrieves the full configuration of a Web Messaging deployment.
    
    Args:
        api_client: The initialized WebchatApi client.
        deployment_id: The unique identifier of the deployment.
        
    Returns:
        dict: The deployment configuration as a Python dictionary.
    """
    try:
        # The SDK method corresponds to the GET endpoint
        response = api_client.get_webchat_deployment(deployment_id)
        
        # The response object contains the body. We convert it to a dict for easier manipulation.
        # In the Genesys SDK, response.body is the model object.
        # We use the to_dict() method if available, or access attributes directly.
        # For newer SDKs, response.body is often a pure dataclass or similar.
        # Here we assume a standard model object that can be serialized.
        
        # Note: The exact serialization method depends on the SDK version.
        # For v130+, we often access the attributes directly or use a helper.
        # Let's access the key attributes directly to ensure compatibility.
        
        config = {
            "id": response.body.id,
            "name": response.body.name,
            "ui": response.body.ui, # This is the critical object for styling
            "routing": response.body.routing,
            "settings": response.body.settings
        }
        
        return config

    except Exception as e:
        print(f"Error retrieving deployment {deployment_id}: {e}")
        raise

Step 2: Modify the UI Configuration

The visual customization of the Web Messaging launcher and chat window is contained within the ui object of the deployment. This object includes properties for colors, fonts, and the launcher button position.

Key properties to modify:

  • launcher.iconColor: Hex code for the launcher icon.
  • launcher.backgroundColor: Hex code for the launcher background.
  • launcher.position: One of left or right (default is usually right).
  • chatWindow.headerBackgroundColor: Hex code for the chat header.
  • chatWindow.agentMessageBackgroundColor: Hex code for agent bubbles.
  • chatWindow.customerMessageBackgroundColor: Hex code for customer bubbles.

Code Example

def customize_deployment_ui(config: dict, ui_changes: dict) -> dict:
    """
    Updates the 'ui' section of the deployment configuration with new visual settings.
    
    Args:
        config: The current deployment configuration dictionary.
        ui_changes: A dictionary containing the new UI settings.
        
    Returns:
        dict: The updated deployment configuration.
    """
    if "ui" not in config:
        config["ui"] = {}
        
    if "ui" not in config["ui"]:
        # Initialize ui object if it does not exist
        config["ui"] = {}

    # Merge launcher settings
    if "launcher" in ui_changes:
        if "launcher" not in config["ui"]:
            config["ui"]["launcher"] = {}
        config["ui"]["launcher"].update(ui_changes["launcher"])
        
    # Merge chat window settings
    if "chatWindow" in ui_changes:
        if "chatWindow" not in config["ui"]:
            config["ui"]["chatWindow"] = {}
        config["ui"]["chatWindow"].update(ui_changes["chatWindow"])
        
    return config

# Define the desired customizations
custom_ui_settings = {
    "launcher": {
        "iconColor": "#FFFFFF",       # White icon
        "backgroundColor": "#0056B3",  # Deep blue background
        "position": "left"            # Move launcher to the left side of the screen
    },
    "chatWindow": {
        "headerBackgroundColor": "#0056B3",
        "agentMessageBackgroundColor": "#E9ECEF",
        "customerMessageBackgroundColor": "#0056B3",
        "customerMessageTextColor": "#FFFFFF"
    }
}

Step 3: Apply the Configuration via API

Once the configuration object is modified, you must send it back to the Genesys Cloud API. You can use PUT to replace the entire deployment or PATCH to update specific fields. For Web Messaging, PUT is often safer if you have the full object, but PATCH is more efficient if you only changed a few fields. However, the Genesys Python SDK for Webchat deployments often exposes a update_webchat_deployment method that maps to PUT.

Important: When using PUT, you must send the complete object structure. If you omit fields like routing or settings, the API may reset them to defaults. This is why Step 1 (Retrieval) is critical.

API Endpoint

PUT /api/v2/webchat/deployments/{deploymentId}

Required Scope: webchat:deployment:write

Code Example

def update_deployment(api_client: WebchatApi, deployment_id: str, config: dict) -> bool:
    """
    Updates the Web Messaging deployment with the new configuration.
    
    Args:
        api_client: The initialized WebchatApi client.
        deployment_id: The unique identifier of the deployment.
        config: The updated deployment configuration dictionary.
        
    Returns:
        bool: True if the update was successful, False otherwise.
    """
    try:
        # Convert the dictionary back to the SDK model object if necessary.
        # In many modern SDKs, you can pass a dictionary or a model object.
        # If the SDK requires a model object, you would instantiate it:
        # from genesyscloud.webchat.models import WebchatDeployment
        # deployment_model = WebchatDeployment(id=config['id'], name=config['name'], ui=config['ui'], ...)
        
        # For this example, we assume the SDK accepts the serialized data or we construct the model.
        # Let's construct the minimal required model for the PUT request.
        # Note: The exact model instantiation varies by SDK version. 
        # A robust approach is to use the existing response body from Step 1 and modify it.
        
        # Since we retrieved the object in Step 1, we should have the original model object.
        # Let's refactor the workflow to keep the model object intact.
        
        pass # Placeholder for logic below
        
    except Exception as e:
        print(f"Error updating deployment {deployment_id}: {e}")
        return False

Refined Workflow: To avoid serialization issues, it is better to modify the SDK model object directly after retrieval.

def update_deployment_direct(api_client: WebchatApi, deployment_id: str, ui_changes: dict) -> bool:
    """
    Retrieves the deployment, modifies the UI model directly, and pushes the update.
    
    Args:
        api_client: The initialized WebchatApi client.
        deployment_id: The unique identifier of the deployment.
        ui_changes: A dictionary containing the new UI settings.
        
    Returns:
        bool: True if the update was successful.
    """
    try:
        # 1. Retrieve the deployment
        response = api_client.get_webchat_deployment(deployment_id)
        deployment_model = response.body
        
        # 2. Modify the UI model directly
        if deployment_model.ui is None:
            deployment_model.ui = {} # Or instantiate the UI model class if required
            
        # Apply launcher changes
        if "launcher" in ui_changes:
            if deployment_model.ui.launcher is None:
                # Instantiate LauncherModel if necessary, or set attributes directly
                # from genesyscloud.webchat.models import WebchatLauncher
                # deployment_model.ui.launcher = WebchatLauncher()
                pass 
                
            for key, value in ui_changes["launcher"].items():
                if hasattr(deployment_model.ui.launcher, key):
                    setattr(deployment_model.ui.launcher, key, value)
                    
        # Apply chat window changes
        if "chatWindow" in ui_changes:
            if deployment_model.ui.chat_window is None:
                # Instantiate ChatWindowModel if necessary
                pass
                
            for key, value in ui_changes["chatWindow"].items():
                # Map camelCase keys from dict to snake_case attributes in Python SDK if needed
                # SDK usually uses snake_case for attributes
                sdk_key = key.replace("BackgroundColor", "_background_color").replace("TextColor", "_text_color").replace("Header", "_header")
                # This mapping is simplified; real code should use explicit attribute names
                if key == "headerBackgroundColor":
                    deployment_model.ui.chat_window.header_background_color = value
                elif key == "agentMessageBackgroundColor":
                    deployment_model.ui.chat_window.agent_message_background_color = value
                elif key == "customerMessageBackgroundColor":
                    deployment_model.ui.chat_window.customer_message_background_color = value
                elif key == "customerMessageTextColor":
                    deployment_model.ui.chat_window.customer_message_text_color = value

        # 3. Push the update
        # The update method typically expects the model object
        api_client.update_webchat_deployment(deployment_id, deployment_model)
        
        print(f"Successfully updated deployment {deployment_id}")
        return True

    except Exception as e:
        print(f"Error updating deployment {deployment_id}: {e}")
        return False

Complete Working Example

This script combines all steps into a single executable file. It retrieves the deployment, applies the custom colors and position, and updates the configuration.

import os
import sys
from genesyscloud.platform.client.configuration import Configuration
from genesyscloud.platform.client.api_client import ApiClient
from genesyscloud.webchat.api import WebchatApi

def main():
    # 1. Initialize Client
    config = Configuration()
    config.client_id = os.getenv("GENESYS_CLIENT_ID")
    config.client_secret = os.getenv("GENESYS_CLIENT_SECRET")
    config.host = os.getenv("GENESYS_HOST", "https://api.mypurecloud.com")
    
    if not config.client_id or not config.client_secret:
        print("Error: Missing GENESYS_CLIENT_ID or GENESYS_CLIENT_SECRET")
        sys.exit(1)
        
    api_client = ApiClient(configuration=config)
    webchat_api = WebchatApi(api_client)
    
    # 2. Define Deployment ID
    deployment_id = os.getenv("GENESYS_DEPLOYMENT_ID")
    if not deployment_id:
        print("Error: Missing GENESYS_DEPLOYMENT_ID")
        sys.exit(1)
        
    # 3. Define Custom UI Settings
    ui_changes = {
        "launcher": {
            "iconColor": "#FFFFFF",
            "backgroundColor": "#0056B3",
            "position": "left"
        },
        "chatWindow": {
            "headerBackgroundColor": "#0056B3",
            "agentMessageBackgroundColor": "#E9ECEF",
            "customerMessageBackgroundColor": "#0056B3",
            "customerMessageTextColor": "#FFFFFF"
        }
    }
    
    # 4. Execute Update
    try:
        print(f"Retrieving deployment {deployment_id}...")
        response = webchat_api.get_webchat_deployment(deployment_id)
        deployment_model = response.body
        
        print("Applying UI customizations...")
        
        # Ensure UI object exists
        if deployment_model.ui is None:
            # Depending on SDK version, you might need to instantiate a UI model
            # from genesyscloud.webchat.models import WebchatUi
            # deployment_model.ui = WebchatUi()
            pass
            
        # Apply Launcher Changes
        if "launcher" in ui_changes:
            if deployment_model.ui.launcher is None:
                # from genesyscloud.webchat.models import WebchatLauncher
                # deployment_model.ui.launcher = WebchatLauncher()
                pass
                
            # Note: Attribute names in the Python SDK are snake_case
            for key, value in ui_changes["launcher"].items():
                if key == "iconColor":
                    deployment_model.ui.launcher.icon_color = value
                elif key == "backgroundColor":
                    deployment_model.ui.launcher.background_color = value
                elif key == "position":
                    deployment_model.ui.launcher.position = value
                    
        # Apply Chat Window Changes
        if "chatWindow" in ui_changes:
            if deployment_model.ui.chat_window is None:
                # from genesyscloud.webchat.models import WebchatChatWindow
                # deployment_model.ui.chat_window = WebchatChatWindow()
                pass
                
            for key, value in ui_changes["chatWindow"].items():
                if key == "headerBackgroundColor":
                    deployment_model.ui.chat_window.header_background_color = value
                elif key == "agentMessageBackgroundColor":
                    deployment_model.ui.chat_window.agent_message_background_color = value
                elif key == "customerMessageBackgroundColor":
                    deployment_model.ui.chat_window.customer_message_background_color = value
                elif key == "customerMessageTextColor":
                    deployment_model.ui.chat_window.customer_message_text_color = value
                    
        # 5. Push Update
        print("Updating deployment...")
        webchat_api.update_webchat_deployment(deployment_id, deployment_model)
        print("Deployment updated successfully.")
        
    except Exception as e:
        print(f"An error occurred: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()

Common Errors & Debugging

Error: 403 Forbidden

  • What causes it: The OAuth Client used does not have the webchat:deployment:write scope.
  • How to fix it: Go to the Genesys Cloud Admin Console, navigate to Admin > Security > OAuth Clients, select your client, and add the webchat:deployment:write scope. Save the changes and regenerate the client secret if necessary.

Error: 422 Unprocessable Entity

  • What causes it: The payload sent to the API is invalid. This often happens if a color code is not a valid hex string (e.g., missing the # or using invalid characters) or if a required field is missing.
  • How to fix it: Validate your hex color codes. Ensure that all required fields in the ui object are present. If you are sending a partial object via PATCH, ensure the structure matches the API specification.

Error: 500 Internal Server Error

  • What causes it: A transient issue on the Genesys Cloud platform.
  • How to fix it: Implement retry logic with exponential backoff. For simple scripts, a manual retry is sufficient. In production, use a library like tenacity or httpx’s built-in retry mechanisms.

Error: AttributeError: ‘NoneType’ object has no attribute ‘launcher’

  • What causes it: The deployment’s ui object or its launcher sub-object was not initialized in the SDK model before attempting to set attributes.
  • How to fix it: Always check if the object is None before accessing its attributes. If it is None, instantiate the appropriate model class (e.g., WebchatLauncher()) and assign it to the parent object.

Official References